2D Toolkit Forum
2D Toolkit => Support => Topic started by: Copywright on January 22, 2013, 08:27:10 pm
-
Hey,
I'm coding a 2D beat-em-up, and I ran into some trouble with my movement script. I keep running into two problem:
- When I am pressing the left arrow, then press the right arrow, the rightWalk animation is playing, but I'm still moving left.
- When all the parameters set for the idle animation are met, the animation doesn't play; it sits on the first frame without playing the animation once.
Here's the code:
void Update () {
leftWalkClipID = Skate.GetClipIdByName ("leftWalk");
rightWalkClipID = Skate.GetClipIdByName("rightWalk");
leftIdleClipID = Skate.GetClipIdByName("leftIdle");
rightIdleClipID = Skate.GetClipIdByName("rightIdle");
if (Input.GetKeyUp(KeyCode.LeftArrow) | Input.GetKeyUp(KeyCode.RightArrow))
{
rigidbody.Sleep();
}
if (Input.GetKeyUp(KeyCode.UpArrow) | Input.GetKeyUp(KeyCode.DownArrow))
{
rigidbody.Sleep();
}
if (rigidbody.IsSleeping())
{
isStandingStill = true;
stillWalking = false;
}
else
{
stillMoving = true;
stillWalking =true;
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
Skate.Play(leftWalkClipID);
isLookingLeft = true;
isLookingRight = false;
stillWalking = true;
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
stillWalking = true;
isLookingLeft = false;
isLookingRight = true;
Skate.Play(rightWalkClipID);
}
if (Input.GetKeyDown(KeyCode.RightArrow) && Input.GetKeyDown(KeyCode.LeftArrow))
{
rigidbody.Sleep();
}
if (Input.GetKeyDown(KeyCode.UpArrow))
{
if ( isLookingLeft == true)
{
Skate.Play(leftWalkClipID);
stillWalking = true;
}
if (isLookingRight == true)
{
Skate.Play (rightWalkClipID);
stillWalking = true;
}
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
if ( isLookingLeft == true)
{
Skate.Play(leftWalkClipID);
stillWalking = true;
}
if (isLookingRight == true)
{
Skate.Play (rightWalkClipID);
stillWalking = true;
}
}
if (Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") == 0)
{
stillMoving = false;
}
if ( stillMoving == true && isStandingStill == true
&& stillWalking == false && isLookingRight == true && isLookingLeft == false)
{
Skate.Play(rightIdleClipID);
}
if (Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") == 0 && isStandingStill == true
&& stillWalking == false && isLookingLeft == true && isLookingRight == false)
{
Skate.Play(leftIdleClipID);
}
How can I fix these two problems? Thanks in advance.
P.S: I apologize for the messiness of my code, I'm just trying to rapidly prototype then organize certain things into classes later on.
-
How do you move your sprite? I don't think I saw any code which did that.
If you're planning on doing something like this, I strongly suggest managing state yourself instead of relying on GetKeyDown. So something like this (bad pseudocode). It makes things a lot simpler to decouple animation from movement.
Vector2 inputMoveDirection;
Vector2 physicalMoveDirection;
inputMoveDirection.x = Input.GetAxis("Horizontal");
inputMoveDirection.y = ...
physicalMoveDirection = UpdatePhysicalMoveDirectionFromInput(inputMoveDirection, physicalMoveDirection);
if (physicalMoveDirection == Vector2.zero) newClip = "idle";
else
{
if (physicalMoveDirection.x < 0) newClip = "walkleft";
else if (physicalMovedirection.x > 0) newClip = "walkright";
float spd = Mathf.Abs(physicalMoveDirection.x);
if (spd > fastMoveSpeed) newClip += "fast";
else ... // handle other speeds
}
if (!anim.IsPlaying(newClip)) anim.Play(newClip); // IsPlaying(clipName) requires 1.90
-
Sorry for leaving the movement out. I decided to use rigidbodies for the brawler, but it's still just testing. If you think there's a better way, please let me know (I'm planning on moving to SmoothMoves for animation soon, so rigidbodies would work better for me the way I see it).
void FixedUpdate() {
Vector3 lrMovement = new Vector3(300, 0, 0);
Vector3 udMovement = new Vector3(0, 300, 0);
if (Input.GetKey(KeyCode.LeftArrow) | Input.GetKey(KeyCode.RightArrow))
{
rigidbody.AddForce(Input.GetAxis("Horizontal") * lrMovement * Time.deltaTime);
isStandingStill = false;
}
if (Input.GetKey(KeyCode.UpArrow) | Input.GetKey(KeyCode.DownArrow))
{
rigidbody.AddForce(Input.GetAxis("Vertical") * udMovement * Time.deltaTime);
isStandingStill = false;
}
}
Anyway, I understand most of what you mean. One thing I'm not getting completely is the physicalMoveDirection. I would be setting it to inputMoveDirection.x and inputMoveDirection.y? Or would I be coding some custom function that updates physicalMoveDirection based on input? Also, why is physicalMoveDirection a parameter of the function I'm using to define it?
Also if I'm setting physicalMoveDirection to the absolute of inputMoveDirection, it'll range from 0 to 1? So fastMoveSpeed would be 0.7 or something like that? That could be great for an automatic run.
Also, what would newClip be exactly? From what it looks like, it's a string, but in the documentation, it says performance is better if I cache playing animations by using the clipID.
Excuse my questions, I'm still trying to pick up Unity :).
-
physicalMoveDirection is the input move direction filtered and process. This could be after acceleration, damping, etc is performed to the inputs. Eg. slowing down before changing direction. It should be signed to signify direction, but if you notice in the pseudocode I posted, I do get the abs to get speed.
If you're only calling it a few times a frame, using the name is fine. Its definitely faster to use clip id, but whether you'd notice the difference with relatively few instances of it is questionable.
-
physicalMoveDirection is the input move direction filtered and process. This could be after acceleration, damping, etc is performed to the inputs. Eg. slowing down before changing direction. It should be signed to signify direction, but if you notice in the pseudocode I posted, I do get the abs to get speed.
If you're only calling it a few times a frame, using the name is fine. Its definitely faster to use clip id, but whether you'd notice the difference with relatively few instances of it is questionable.
So basically, physicalMoveDirection would operate the same as inputMoveDirection, but no rely on input? But, if it gets its value from input, wouldn't be the same as just using inputMoveDirection since physicalMoveDirection only changed when input occurs?
-
It derives its value from input, doesn't need to necessarily correspond directly to inputMoveDirection. If you want them to be the same, that would work too, but all actions would be very abrupt.
-
Ah, I understand now. Thanks, I will try it. However, what about the vertical axis? I want to be is the player was last moving left, and wants to move up, the leftwalk animation would play, and vice-versa. Do you have any idea how I'd go about making it like so using physicalMoveDirection?
And here's the function I've come up with:
void UpdatePhysicalMoveDirection(Vector2 inptVector, Vector2 directionVector)
{
if(inptVector.x > 0)
{
directionVector.x += inptVector.x;
}
else if (inptVector.x < 0)
{
directionVector.x -= inptVector.x;
}
if(inptVector.y > 0)
{
directionVector.y += inptVector.y;
}
else if (inptVector.y < 0)
{
directionVector.y -= inptVector.y;
}
}
Would that work?
-
You'd want to clamp it, and also scale by Time.deltaTime...