Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by SineDeviance · Aug 19, 2013 at 08:10 PM · animationmovementvelocitydirectionisometric

Getting animations to play relative to player's direction?

New code:

 var speed : float = 1;
 var gravity : float = 20;
 var lookSpeed = 4.0;
 
 function Start () {
 
     var abdomenMix : Transform = transform.Find("Armature/Pelvis_C/Abdomen");
     
     animation["HGun_Fire"].wrapMode = WrapMode.Once;
     animation["HGun_Fire"].layer = 2;
     animation["HGun_Fire"].AddMixingTransform(abdomenMix);
     
 }
 
 function Update(){
 
     var playerPlane = new Plane(Vector3.up, transform.position);
     var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
     var hitdist = 0.0;
 
     if (playerPlane.Raycast (ray, hitdist)) {
         var targetPoint = ray.GetPoint(hitdist);
         var targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
         transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, lookSpeed * Time.deltaTime);
     }
 
     var velx: Vector3 = Camera.main.transform.forward * Input.GetAxis("Vertical");
       var velz: Vector3 = Camera.main.transform.right * Input.GetAxis("Horizontal");
       var vely: Vector3 = transform.up * -gravity;
   
       velx.y = 0;
       velz.y = 0;
       
       var flatVel = velx + velz;
       
       var localVel = transform.TransformDirection(flatVel);
 
       var controller = GetComponent(CharacterController);
       
       controller.Move((flatVel + vely) * speed * Time.deltaTime);
       
       if (localVel.x >= 0.25) {
         animation.CrossFade("Walk");
           }
       
     else if (localVel.x <= -0.25) {
         animation.CrossFade("Backpedal");
         }
     
     else if (localVel.z >= 0.25) {
         animation.CrossFade("StrafeR");
         }
         
     else if (localVel.z <= -0.25) {
         animation.CrossFade("StrafeL");
           }
                     
       else {
           animation.CrossFade("Idle");
           }
 }

////////////////////////

Hi all! I am trying to get a movement script to play nice with animations. The game uses an ortho-isometric camera and so the movement is based on Camera.main.transform, which works perfectly, but I'm having trouble getting animations to play relative to player direction.

Basically, what I need to accomplish is this - when the player is actually walking in his forward direction, play Walk. When he is walking in his left direction, play StrafeL. And so on, etc. I have tried comparing the if statement to various movement-related things, but the obvious choices don't seem to work. Comparing it against Input.GetAxis("foo") likewise doesn't work, because those axes are relative to the camera, not the player.

EDIT: Forgot to mention, the player's look direction is always based on the position of the mouse cursor relative to a plane.

Here's the script as it currently is:

 var speed : float = 1;
 var gravity : float = 20;
 var lookSpeed = 4.0;
 
 function Start (){
 
     var abdomenMix : Transform = transform.Find("Armature/Pelvis_C/Abdomen");
     
     animation["HGun_Fire"].wrapMode = WrapMode.Once;
     animation["HGun_Fire"].layer = 2;
     animation["HGun_Fire"].AddMixingTransform(abdomenMix);
 }
 
 function Update(){
 
     var playerPlane = new Plane(Vector3.up, transform.position);
     var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
     var hitdist = 0.0;
 
     if (playerPlane.Raycast (ray, hitdist)) {
         var targetPoint = ray.GetPoint(hitdist);
  
         var targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
 
         transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, lookSpeed * Time.deltaTime);
     }
 
     var velx: Vector3 = Camera.main.transform.forward * Input.GetAxis("Vertical");
       var velz: Vector3 = Camera.main.transform.right * Input.GetAxis("Horizontal");
       var vely: Vector3 = transform.up * -gravity;
   
       velx.y = 0;
       velz.y = 0;
 
       var controller = GetComponent(CharacterController);
       
       if (!Input.GetAxis("Vertical") && !Input.GetAxis("Horizontal")) {
           animation.CrossFade("Idle");
           }
   
    
       if (velx == true) {
         animation["Walk"].speed = 0.65;
           animation.CrossFade("Walk");
           }
   
       if (-velx == true) {
           animation["Backpedal"].speed = 0.5;
           animation.CrossFade("Backpedal");
           }
   
       if (vely == true) {
           animation["StrafeR"].speed = 0.65;
           animation.CrossFade("StrafeR");
           }
   
       if (-vely == true) {
           animation["StrafeL"].speed = -0.5;
           animation.CrossFade("StrafeL");
           }
       
       controller.Move(vely * gravity * Time.deltaTime);
 
       controller.Move(velx * speed * Time.deltaTime);
       controller.Move(velz * speed * Time.deltaTime);
 }

If anyone knows what I'm missing here, I would greatly appreciate the help :D

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by SineDeviance · Aug 21, 2013 at 12:15 AM

I finally figured it out! It was a combination of the x and z axes being mapped backwards and not using InverseTransformDirection. Here is the working code:

 var speed : float = 1;
 var runSpeed : float = 2;
 var gravity : float = 20;
 var lookSpeed = 4.0;
 
 private var varSpeed : float;
 
 function Start () {
 
     var chestMix : Transform = transform.Find("Armature/Pelvis_C/Abdomen/Chest");
     
     animation["HGun_Fire"].wrapMode = WrapMode.Once;
     animation["HGun_Fire"].layer = 2;
     animation["HGun_Fire"].AddMixingTransform(chestMix);
     
 }
 
 function Update(){
 
     var playerPlane = new Plane(Vector3.up, transform.position);
     var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
     var hitdist = 0.0;
 
     if (playerPlane.Raycast (ray, hitdist)) {
         var targetPoint = ray.GetPoint(hitdist);
         var targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
         transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, lookSpeed * Time.deltaTime);
     }
 
     var vel: Vector3 = Camera.main.transform.forward * Input.GetAxis("Vertical") + Camera.main.transform.right * Input.GetAxis("Horizontal");
       var vely: Vector3 = transform.up * -gravity;
       
       vel.y = 0;
                   
       var localVel = transform.InverseTransformDirection(vel);
 
       var controller = GetComponent(CharacterController);
       
       controller.Move((vel.normalized * varSpeed * Time.deltaTime) + (vely * Time.deltaTime));
       
       if (localVel.z > 0.1) {
           animation["Walk"].speed = 0.65;
         animation.CrossFade("Walk");
         //Debug.Log("Should be walking "+localVel.z);
           }
       
     else if (localVel.z < -0.1) {
         animation["Backpedal"].speed = 0.65;
         animation.CrossFade("Backpedal");
         //Debug.Log("Should be backpedalling "+localVel.z);
         }
         
     else if (localVel.x > 0.0) {
         animation["StrafeR"].speed = 0.65;
         animation.CrossFade("StrafeR");
         //Debug.Log("Should be strafing right "+localVel.x);
         }
         
     else if (localVel.x < -0.0) {
         animation["StrafeL"].speed = 0.65;
         animation.CrossFade("StrafeL");
         //Debug.Log("Should be strafing left "+localVel.x);
         }
     
       else {
           animation.CrossFade("Idle");
           }
           
       if(Input.GetButton("Sprint")) {
           varSpeed = runSpeed;
           animation["Walk"].speed = 1.3;
           animation["Backpedal"].speed = 1.3;
           animation["StrafeR"].speed = 1.3;
           animation["StrafeL"].speed = 1.3;
           }
       else {
           varSpeed = speed;
           }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by OP_toss · Aug 19, 2013 at 08:25 PM

The best way to do this is to place a gameobject above your animated object's root. Then rotate the parent game object based on input. This will rotate the animating child object.

I recommend always placing at least 1 gameobject between your controller scripts and your animated model. That way you always have another degree of control, and you can easily swap out models if needed.

Hope this helps!

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image SineDeviance · Aug 19, 2013 at 08:41 PM 0
Share

Thanks for the reply OP_toss, but that doesn't answer my question. I have no problem getting the player to rotate. His animations don't play properly relative to his rotation :D

That is still a good idea, and I will make sure I re-create my player prefab with that setup.

avatar image OP_toss · Aug 19, 2013 at 11:17 PM 1
Share

I believe that is what you mean... The only reason the animations wouldn't play relative to your rotation, is that either your rotation is being set on the animated object, which will be overwritten by the animation, OR the animation is wrong. If the second is the case, just change your animations to always face straight, then you can rotate the parent in the setup I described above.

Am I still off in my understanding? Sorry if so, hope this helps!

avatar image SineDeviance · Aug 19, 2013 at 11:25 PM 0
Share

It's actually neither of those things, there's nothing wrong with the animations (they're all at root point with no rotation.) The player's rotation is deter$$anonymous$$ed by the position of the mouse cursor as per the script, not by the animations. I am not using $$anonymous$$ecanim, I am using regular animations with a rig set to legacy.

None of this is related to the problem, though. The problem is that when the character is facing a direction (let's say 270 degrees) on the plane, and he moves forward, I need his Walk animation to play and reflect that he is moving forward. When he's facing that same direction and he moves sideways, I need his sidestrafe animations to play and reflect that he is strafing in whichever direction is relevant (left, right.) And the same goes for the same direction and backpedalling. Does this many any sense? Am I babbling like a madman? :D

If it still doesn't, let me know and I'll post a web build so you guys can see what I mean. Thanks for trying to help, though :D

avatar image
1

Answer by Loius · Aug 19, 2013 at 11:35 PM

(I'm not sure what you get when you use a V3 as a boolean (if -vely==true), but I doubt it's what you want)

You should really combine your vectors. You can get down to one Move call (from three!) and you can also translate that movement vector into local space:

 flatVel = velx + velz;
 
 localVel = transform.TransformDirection(flatVel);
 
 if ( localVel.x < 0 ) Left;
 if ( localVel.x > 0 ) Right;
 if ( localVel.z > 0 ) Forward;
 if ( localVel.z < 0 ) Back;

 controller.Move(flatVel + vely);
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image OP_toss · Aug 20, 2013 at 01:20 AM 1
Share

Ah I think I see what you mean now... and yes this guy's answer is I think what you want. Didn't know it was as simple as knowing which animation to call hah. GJ Loius

Also it'd be nice if you didn't even have to transform into local space, and you just worked in local space to begin with. And I'd just make a few of those else if's, but that looks good to me!

avatar image SineDeviance · Aug 20, 2013 at 01:33 AM 0
Share

Loius, that looks to be exactly the kind of solution I needed. I'll try it out tomorrow and report back. Thanks a bunch!

avatar image SineDeviance · Aug 20, 2013 at 04:47 AM 0
Share

It's so close to working!

Okay, using the new code example I posted at the top of my original question, the player's animations are AL$$anonymous$$OST working properly. They seem to work in the expected fashion if he is facing up or down relative to the camera. However, if he is facing left or right relative to camera, the animations play backwards for some reason. Any ideas on how I could solve that? Did I do something wrong? =D

Thanks again, Loius, for the idea of combining the vectors into new variables.

EDIT: If you are wondering why I compared the if statements against 0.25, it is because comparing against 0 or 0.1 had odd effects. When the player would stop moving completely, ins$$anonymous$$d of crossfading to 'Idle' it would simply keep looping whatever animation was currently playing (it's as if Unity thinks the player is still moving even though he is not.)

I have no idea why this happens. It'd be nice to figure that out as well =D

avatar image SineDeviance · Aug 20, 2013 at 05:11 AM 0
Share

$$anonymous$$ore odd stuff happening. In .$$anonymous$$ove() I changed flatVel to localVel just to see what direction the player thought he was moving in. Well, it turns out all the vectors are off by about 45 degrees, but not quite. It's also as if his center of rotation is off by about half a unit.

If he is facing directly up relative to camera, for example, and I try to move him upward, he actually moves in a kind-of up/right direction. If I am moving and rotate the mouse around him to make him rotate, he kind of swings around. I don't know how to explain it any better. All possible directions seem to be affected the same way. I have no idea what is causing this.

avatar image Loius · Aug 20, 2013 at 02:38 PM 0
Share

I think it might be InverseTransformDirection, ins$$anonymous$$d of TransformDirection. I can never keep those two straight, honestly. Try Inverse and see if that helps first.

If it's just picking the wrong one of the Left and Right options, you can switch the if checks (so that +X becomes Left ins$$anonymous$$d of Right). I've been known to make silly mistakes with simple things :)

Floating point values usually aren't zero unless you set them directly to zero, but I'm not sure why comparing to 0.1 would never go idle. Could be you still have a tiny bit of input co$$anonymous$$g from a joystick.

transform.TransformDirection is using "this" object's transform as the reference point. That transform's forward direction (local +Z) should match up with the graphical representation's forward (the way you expect to walk when you just press W or whatever).

avatar image
0

Answer by Machineman · Nov 06, 2015 at 01:44 PM

I know this is an old post, but I have struggled with this issue as well. I have made a way simpler solution to play animations based on movement and direction, and have made an asset on the Unity Asset store.

Check it out!: https://www.assetstore.unity3d.com/#!/content/47778

Happy game developing!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

error CS0019: trying to increase velocity when key is pressed twice in quick succession 1 Answer

I have a value that determines which way my character is facing in degrees. How do I convert that value to a range of -1 to 1 for smooth mecanim bleend tree animation? 0 Answers

Third-person character animations based on World-relative input and Y-rotation (looking at mouse position) 1 Answer

Get the sin of an angle between vector3.forward and direction character is moving 1 Answer

Character facing wrong direction when moving vertically 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges