Wc3C.net

Wc3C.net (http://www.wc3c.net/forums.php)
-   JASS/AI scripts tutorials (http://www.wc3c.net/forumdisplay.php?f=650)
-   -   How to instantly set a unit's facing (http://www.wc3c.net/showthread.php?t=105830)

grim001 05-07-2009 12:46 PM

How to instantly set a unit's facing
 
1 Attachment(s)
So, you want to recycle dummy units for your projectile system, but you've run into a problem that has plagued mapmakers forever. You can't instantly set the facing of a unit. Turns out there is a way to do it, but it will take a little work, and it is limited. But it's enough to successfully implement dummy recycling for most projectiles.

First of all, an edit to the dummy.mdx file is required. I have attached the edited dummy.mdx to this post, so you don't have to follow these steps, but this is how it was changed.

1.) Download vexorian's xe system.

2.) Export the dummy.mdx model from the map.

3.) Use an mdx <-> mdl converter such as this one to convert it into an mdl file.

4.) Edit the file at the following point:
Code:

Helper "Bone_Root" {
        ObjectId 0,

Change this into:
Code:

Helper "Bone_Head" {
        ObjectId 0,


5.) Save the changes and convert it back from mdl to mdx.

OK, so now you know the steps that were taken to change the dummy model. If you downloaded the attached dummy model, you should follow the directions starting from here:

1.) Import the new dummy.mdx into your map.

2.) Create a dummy unit. Change "Art - Animation - Blend Time (seconds)" to 0 seconds.

3.) Change the dummy unit's model to the dummy.mdx file.

4.) Copy the following functions into your map:
Collapse JASS:
// To make the dummy face a 2 dimensional orientation instantly:
function SetDummyFacing takes unit u, real angle returns nothing
    call SetUnitLookAt(u, "Bone_Head", u, Cos(angle)*1000000., Sin(angle)*1000000., 0.)
endfunction

// To make the dummy face a 3 dimensional orientation instantly:
function SetDummyOrientation takes unit u, real x, real y, real z returns nothing
    call SetUnitLookAt(u, "Bone_Head", u, x*1000000., y*1000000., z*1000000.)
endfunction

//To make the dummy always face a particular unit, for homing missiles:
function SetDummyHomingTarget takes unit u, unit target returns nothing
    call SetUnitLookAt(u, "Bone_Head", target, 0., 0., 0.)
endfunction

5.) Create the dummy unit in game and attach your projectile's model to it.

6.) Call one of the above functions on your projectile. You should only do this once per time the projectile is recycled. If you try to call these functions continuously, it won't animate correctly.

You can't use this instant facing stuff in conjunction with the dummy model's pitch animations. The dummy will be pitched at an angle that matches its real facing, not the fake facing we have given it by adjusting the head bone.

So, this trick is only useful for projectiles that face one angle or follow one unit and never change from that until they get recycled. It is possible to change the angle or target while the projectile is still being used, but most likely the unit will flicker to face the wrong direction for an instant if you do so. By only calling these functions as the unit gets recycled, that flicker can be concealed from the player.

Why do I want to recycle projectiles anyway?

Every time you create a new unit and destroy it, WC3's memory use goes up and doesn't seem to come back down. It causes performance degradation over time even if you don't leak.

Creating units is just about the slowest thing possible in WC3, too. If you try to make a machine gun that fires 20 bullets per second by creating dummy units, you will lag. With unit recycling, I have made a machine gun that can fire over 200 bullets per second before the framerate starts to dip (and I am sure it was because of the 200 bullets traveling, not because of creating 200 bullets). And if 200 bullets per second sounds excessive, just imagine that as 10 players each firing the 20 bullet per second machine guns.

Whether you notice any improvement in a particular map is going to depend on how many projectiles it creates over time and what interval they're created at. I highly recommend unit recycling for any shooter-type map that has guns firing at a high frequency. For other types of games, unit recycling should be optional.

To be added:
A guide on how to actually implement projectile recycling.
A test map demonstrating everything.

Rising_Dusk 05-07-2009 05:26 PM

Fix some of your bbcode errors (you have a bold misuse in there) and then maybe add a testmap or something. Also, since you talk so much about recycling the dummies, you will want to explain just how to 'recycle' the dummies faced in this manner so that they can be reused later.

I read it over and like it on the whole, though, so if you do those things I'll go ahead and approve this.

Bobo_The_Kodo 05-08-2009 03:13 AM

One problem!

The SetUnitLookAt uses terrain height ...

so on a hill this will face wrong pitch

edit: more complicated than this to get it to work usefullly

grim001 05-08-2009 03:24 AM

Quote:

Originally Posted by Bobo_The_Kodo
One problem!

The SetUnitLookAt uses terrain height ...

so on a hill this will face wrong pitch


This is wrong, terrain heights only exist in a range of several thousand. When you multiply the X and Y coordinates by 1,000,000 each, the incorrectness of the Z orientation would become completely negligible.

And that's if what you're saying were true, but double check the function... the unit is looking at itself with an offset, meaning it already has its own Z height factored in.

It works fine when I use it in my physics engine.

MaD[Lion] 05-08-2009 12:50 PM

this + infrane's dummy will be awesome

grim001 05-08-2009 01:37 PM

What is infrane's dummy?

Bobo_The_Kodo 05-08-2009 02:02 PM

Quote:

This is wrong, terrain heights only exist in a range of several thousand. When you multiply the X and Y coordinates by 1,000,000 each, the incorrectness of the Z orientation would become completely negligible.

And that's if what you're saying were true, but double check the function... the unit is looking at itself with an offset, meaning it already has its own Z height factored in.

It works fine when I use it in my physics engine.

Bah, right of course

I don't know what I was thinking ...

Rising_Dusk 05-08-2009 02:43 PM

1 Attachment(s)
Quote:

Originally Posted by grim001
What is infrane's dummy?

It is Anitarf's/Infrane's; the pitch dummy with ~180 animations. See attached.

grim001 05-08-2009 03:03 PM

Is there actually any difference between that and the xe dummy? I can't really see one after looking at it.

MadLion, sorry to burst your bubble if you thought you could get 360 degree rotations from combining this with the pitch animations:
Quote:

Originally Posted by grim001
You can't use this instant facing stuff in conjunction with the dummy model's pitch animations. The dummy will be pitched at an angle that matches its real facing, not the fake facing we have given it by adjusting the head bone.


Once I make a demo map for this tutorial I'm going to check out if there are any more possibilities when you make the dummy face a hidden unit, maybe we can still get 360 degree rotations working smoothly, don't count on it though.

Rising_Dusk 05-08-2009 03:11 PM

Vex made the xe dummy long after Inf/Ani made the pitch dummy, so some older users still use Inf/Ani's just because there's really no need to update to xe's as it is the same.

Bobo_The_Kodo 05-09-2009 04:54 AM

Quote:

Once I make a demo map for this tutorial I'm going to check out if there are any more possibilities when you make the dummy face a hidden unit, maybe we can still get 360 degree rotations working smoothly, don't count on it though.

Rawr, I did these tests..

SetUnitLookAt only updates approximately every 0.2 seconds..

So its like dusk's choppy knockback system

x4...

(and also you can't do pitch properly with this (unless you can somehow do negative fly heights at runtime?))

edit: it also takes a long time to get the dummy unit set to proper spot -> need to put on edge of map if you want projectile dummies not to glitch

edit2: attached testmap (tx,ty on setdummyfacing should be simplified (im overcomplicating by far) ), so you can see the choppyness!

edit3: i probably will still use the way attached in testmap for my own spells, but not have a curving projectile or like that, just to change direction at a chop

grim001 05-09-2009 08:35 AM

1 Attachment(s)
What's with all of the unnecessary and ugly code in that test map?

It's not SetUnitLookAt that won't update, it's your SetDummyFacing function that's incorrect. It is deliberately designed to only pick one of 8 angles rather than rotating in a complete circle. Try using my function instead of yours and you will see that the facing angle updates instantly, but flickers to an incorrect direction each time it's set.

If you want a unit to achieve perfectly smooth rotation you need to make it follow another unit, I included a test map to demonstrate.

If you want to manipulate a unit's pitch, there are four ways that work:
1.) Make your projectile face any 3 dimensional orientation you want when it spawns, and leave it that way until the projectile gets recycled.
2.) Make your projectile face a homing target, it will naturally pitch to face it and it will animate smoothly.
3.) If you want to set pitch to an arbitrary value, you need to make the dummy unit follow another invisible unit. But you can't pitch straight down unless the projectile is in the air, otherwise the invisible unit can't fit underneath it.
4.) Or just use the pitch animations of the dummy unit, but you can't combine these with any sort of instant facing. If you want instant facing too you would need to create a new unit.

Toadcop 05-09-2009 11:49 AM

Quote:

Every time you create a new unit and destroy it, WC3's memory use goes up and doesn't seem to come back down. It causes performance degradation over time even if you don't leak.
lol. i wrote this long ago... and "no one" belived me... especially person called Vexorain <_<

btw post what the original idea is by Litany... (afaik) at least i readed this at least ~1 year ago or maybe even earlier.

Quote:

// To make the dummy face a 2 dimensional orientation instantly:
function SetDummyFacing takes unit u, real angle returns nothing
call SetUnitLookAt(u, "Bone_Head", u, Cos(angle)*1000000., Sin(angle)*1000000., 0.)
endfunction

it takes radians or angles ? (imagine it's not SO obvious especialy for users...) looks like radians.

imo for alot objects it may cause performance lose. (wc3 need to rotate model every frame) but ofc i don't know how exactly and much it will degrade it. (cause the initial purporse of this are cinematics)

grim001 05-09-2009 01:32 PM

Quote:

Originally Posted by Toadcop
btw post what the original idea is by Litany...(afaik) at least i readed this at least ~1 year ago or maybe even earlier.

Well I'm not claiming I invented the idea. But no one has used it for a long time and I'm not sure if anyone ever got it working usefully.

Quote:

Originally Posted by Toadcop
imo for alot objects it may cause performance lose. (wc3 need to rotate model every frame)

It has no effect on performance that I can notice. I've tested this with a lot of bullets at once in my physics engine.

Bobo_The_Kodo 05-09-2009 05:18 PM

Quote:

It's not SetUnitLookAt that won't update, it's your SetDummyFacing function that's incorrect. It is deliberately designed to only pick one of 8 angles rather than rotating in a complete circle. Try using my function instead of yours and you will see that the facing angle updates instantly, but flickers to an incorrect direction each time it's set.

I disagree.

I just set bounds so that it thinks map is really small, and guess what?
It worked fine

It appears its based on distance or something...? (yes, view 3rd testmap)

(but yes I need to clean code for SetDummyFacing)

Edit: And a second testmap, with it as a constant distance toward the angle... the problem with this is you need to call UpdateDummyFacing( unit ) whenever you move dummy

Also, I need to find out how to set unit fly height negative, I'll ask Litany

Edit: And a third testmap, proving it updates at a lower frequency from higher distance (blizzard probably thought the unit would move smaller % of angle change, = distance moved / distance between units..)


All times are GMT. The time now is 03:11 PM.

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services