My player is switching between animations when it is not programed to - c#

When my player is moving, the animation switches between idle and walk when I am holding down D. I played the animation and it looks fine but when I play the transition it starts idle and switches to walk. I have tried creating a new project and doing it again but it does the same thing. Does anyone know how to fix this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField]
float moveForce = 10f;
[SerializeField]
float jumpForce = 11f;
float movementX;
Rigidbody2D myBody;
Animator Anim;
private SpriteRenderer sr;
string WALK_ANIMATION = "Walk";
private void Update()
{
playerMoveKeyboard();
animatePlayer();
}
private void Awake()
{
myBody = GetComponent<Rigidbody2D>();
Anim = myBody.GetComponent<Animator>();
sr = GetComponent<SpriteRenderer>();
}
void playerMoveKeyboard()
{
movementX = Input.GetAxisRaw("Horizontal");
transform.position += new Vector3(movementX, 0f, 0f) * moveForce * Time.deltaTime;
}
void animatePlayer()
{
if(movementX > 0)
{
Anim.SetBool(WALK_ANIMATION, true);
sr.flipX = false;
}
else if (movementX < 0)
{
Anim.SetBool(WALK_ANIMATION, true);
sr.flipX = true;
}
else
{
Anim.SetBool(WALK_ANIMATION, false);
}
}
}

Not sure if I am seeing the problem correctly from the gif, but can't you just turn off "Has exit time" and change the transition duration to 0?

Not sure but using a float instead of a bool to decide when to play the animation might solve this. That is how I've been doing it and never had any problems.
Do this by creating a new parameter in the animator called "Speed". Change the condition from idle to walk to Speed greater 0.01 and walk to idle to Speed less 0.01 or some other small number.
In the code you can change "Speed" to the player speed by adding:
anim.setFloat("Speed", Mathf.Abs(movementX))
to the update function inside the player movement script.
You should also remove the Anim.SetBool() from the funciton animatePlayer().

Related

How to prevent speeding of rigidbodies used to control characters

I have a player in unity with the movement controlled by a rigidbody. The movement on the Z axis is kept contstant by the game to keep the player moving forward. However, this means that the rigidbody keeps speeding up so its speed at the start of the game is much slower than the speed at the end of the game. Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
public class Controller : MonoBehaviour
{
[Tooltip("Rigidbody component attached to the player")]
public Rigidbody rb;
public float forwardMax;
public float slowBy;
private float movementX;
private float movementY;
private float gravity = -9.81f;
private bool isJumping = false;
private bool isSlowing = false;
private bool isSpeeding = false;
private float speedX = 100;
private float speedY = 150000;
private float speedZ = 60;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
// if(!controller.isGrounded)
// {
// Vector3 gravityVector = new Vector3(0.0f, gravity, 0.0f);
// rb.AddForce(gravityVector * Time.deltaTime);
// }
}
void OnCollisionEnter(Collision collision)
{
// SceneManager.LoadScene(1);
}
// Update is called once per frame
void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
void OnJump()
{
isJumping = true;
}
void CalculateMovement()
{
if(rb.velocity.z > 20)
{
rb.drag = 20;
}
else
{
rb.drag = 0;
}
Vector3 movement = new Vector3(movementX * speedX, 0.0f, speedZ);
if(isJumping)
{
movement.y += Mathf.Sqrt(speedY * -3.0f * gravity);
isJumping = false;
}
rb.AddForce(movement);
Debug.Log("Speed is " + rb.velocity.z);
}
void FixedUpdate()
{
CalculateMovement();
}
}
Is there a way to keep the forward velocity constant? The problem is worse when the player jumps.
First I tried clamping the forward (z-axis) vector but that had no effect. Then, I tried adding a backward vector onto the total when the forward velocity was above a certain number but this led to it speeding up and slowing down all the time. Then I tried the same thing with the drag on the rigidbody but that had the same effect.
You can use rigidbody.velocity and set it to constant value or whatever you want instead of adding force. By adding force, your character's speed increases.
Also you can use AddForce but you have to tune the force value dynamically according to the current velocity.
rigidbody velocity
How about directly setting the z value you want at the end of FixedUpdate() ?
......
void FixedUpdate()
{
CalculateMovementWithoutZMovement();
rb.velocity = new Vector3 (rb.velocity.x, rb.velocity.y, ConstantZValue);
}

EnemyAI script not moving the Enemy

I am making my first foray into AI, specifically AI that will follow the player.
I am using the A* Path finding project scripts, but used the Brackeys tutorial for the code
https://www.youtube.com/watch?v=jvtFUfJ6CP8
Source in case needed.
Here's the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class EnemyAI : MonoBehaviour
{
public Transform Target;
public float speed = 200f;
public float NextWayPointDistance = 3f;
Path path;
int currentWaypoint = 0;
bool ReachedEndOfpath = false;
Seeker seeker;
Rigidbody2D rb;
public Transform EnemyGraphics;
// Start is called before the first frame update
void Start()
{
seeker = GetComponent<Seeker>();
rb = GetComponent<Rigidbody2D>();
InvokeRepeating("UpdatePath", 0f, 1f);
}
void UpdatePath()
{
if (seeker.IsDone())
seeker.StartPath(rb.position, Target.position, OnPathComplete);
}
void OnPathComplete(Path p)
{
if (!p.error)
{
path = p;
currentWaypoint = 0;
}
}
// Update is called once per frame
void fixedUpdate()
{
if(path == null)
return;
if(currentWaypoint >= path.vectorPath.Count)
{
ReachedEndOfpath = true;
return;
}
else
{
ReachedEndOfpath = false;
}
Vector2 Direction = ((Vector2)path.vectorPath[currentWaypoint] - rb.position).normalized;
Vector2 Force = Direction * speed * Time.fixedDeltaTime;
rb.AddForce(Force);
float distance = Vector2.Distance(rb.position, path.vectorPath[currentWaypoint]);
if(distance < NextWayPointDistance)
{
currentWaypoint++;
}
if(rb.velocity.x >= 0.01f)
{
EnemyGraphics.localScale = new Vector3(-1f, 1f, 1f);
}else if(rb.velocity.x <= 0.01f)
{
EnemyGraphics.localScale = new Vector3(1f, 1f, 1f);
}
}
}
How I tried to fix the issue:
I thought it could've been a problem with the speed so I increased it to 10000000, and still nothing
Next I thought it was a problem with the Rigidbody2d so I check there, found the gravity scale was set at 0, so I increased it to 1. It made my enemy fall to the ground but still no movement.
I thought it could've been a problem with the mass and drag, so I set Linear drag and Angular drag to 0, and also set mass to 1. Still nothing.
I set the body type to kinematic, pressed run, nothing. Set the body type to static, pressed run, nothing. Set the body type to Dynamic, pressed run, still nothing.
I tried to make a new target for the enemy to follow, dragged the empty game object i nto the target, pressed run and still didn't move.
I am at a loss on how to fix this.
Please help?
Looks like maybe a typo? You have:
// Update is called once per frame
void fixedUpdate()
{
but the method is called FixedUpdate(), with a big F in front. You have fixedUpdate, which is NOT the same.

Cant Change Friction of Player In Unity2D

I am extremely new to both Unity and C# and have been working on it for a few days. I'm currently trying to stop my player from sliding and to do this I've set the friction value of the players material high so that it doesn't slide. This however creates an issue where my character travels entirely too fast. To get around this I created a child object with a BoxCollider2D tagged as Friction Controller that I can modify. I get a code that changes the friction value of the physics material to 0 when i start moving and 100 when am supposed to stop. The problem is that while this updates the material itself it does not affect the box colliders settings. Does anybody know a solution for this?
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;
public class Player_Movement : MonoBehaviour
{
GameObject frictionController;
public BoxCollider2D collider;
public float speed = 400f;
public float jumpForce;
private float friction;
private Rigidbody2D rb2d;
private bool isMoving;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D> ();
}
// Update is called once per frame
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
Vector2 movement = new Vector2(moveHorizontal,0);
rb2d.AddForce(movement * speed);
}
void Update()
{
frictionController = GameObject.FindWithTag("Friction Controller");
collider = frictionController.GetComponent<BoxCollider2D>();
if (Input.GetKey("a") || (Input.GetKey("d")))
{
{ Debug.Log("Pressed Button"); }
collider.sharedMaterial.friction = 0;
} else { collider.sharedMaterial.friction = 100; }
///This part isn't complete yet
float moveVertical = Input.GetAxis("Vertical");
Vector2 jump = new Vector2(0, moveVertical);
if (Input.GetKeyDown("space"))
{
rb2d.AddForce(Vector3.up * jumpForce);
}
}
}
I'm not sure that your approach is a particularly good one and is likely to give you problems later on. Since you're using the physics system, a better approach would be to apply a force to your Rigidbody that is the OPPOSITE of its velocity when want it to come to a stop.
Nevertheless here is a solution that effectively does what you want to do using a similar approach to what you're attempting. Rather than manipulating the physics material properties, this solution manipulates the drag value of the rigidbody.
public class Player_Movement : MonoBehaviour
{
private Rigidbody2D rb2d;
private float speed = 100f;
void Start()
{
rb2d = GetComponent<Rigidbody2D> ();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
Vector2 movement = new Vector2(moveHorizontal,0);
rb2d.AddForce(movement * speed);
}
void Update()
{
if (Input.GetKey(KeyCode.A) || (Input.GetKey(KeyCode.D)))
{
rb2d.drag = 5; // Adjust this value to modify speed
}
else
{
rb2d.drag = 100; // Adjust this value to modify slippery-ness
}
}
}

How can I make the npc character to rotate slowly facing the player while changing animator transitions?

I have in the soldier animator a Grounded transition and this is start with this transition by default. Then I did that after 3 second it will slowly change between the two transitions from Grounded to Rifle_Aiming_Idle.
But To see how it's working and if it's working good like I wanted I had to turn off the FPSController Camera( FPSCamera is turned off gray ). So when running the game the active camera is the Main Camera and the CM vcam1 ( Cinemachine virtual camera ).
But I want to make more with this cutscene.
I want that first the cutscene will start only when the player the FPSController will exit a door:
This script is attached to the FPSController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class SpaceshipCutscene : MonoBehaviour
{
public Transform player;
public Transform npc;
public float cutsceneDistance = 5f;
public float speed;
private bool moveNpc = false;
// Use this for initialization
void Start()
{
}
private void Update()
{
if (moveNpc)
{
float travel = Mathf.Abs(speed) * Time.deltaTime;
Vector3 direction = (player.position - npc.position).normalized;
Quaternion lookrotation = Quaternion.LookRotation(direction);
npc.rotation = Quaternion.Slerp(npc.rotation, lookrotation, Time.deltaTime * 5);
Vector3 position = npc.position;
position = Vector3.MoveTowards(position, player.position, travel);
npc.position = position;
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.name == "Horizontal_Doors_Kit")
moveNpc = true;
}
}
I want that when the player the FPSController exit the door start the cutscene and while it's playing/doing the cutscene I want at the same time also making the soldier with the animator to rotate slowly facing the FPSController.
FPSController exit the door > Soldier changing slowly from grounded to aiming mode and Soldier rotating slowly facing the FPSController.
My problems are how to start the cinemachine cutscene when the FPSController exit the door and how to make the Soldier( npc ) to rotate slowly facing the FPSController.
What I tried in the Update in the script is not working good.
It's making the npc moving and not rotating slowly good enough fro the cutscene like I wanted.
And maybe for the rotation part I should use the Cinemachine and not doing it in the script ? Maybe I should using Timeline here too for the rotation part ?
Working solution for what I needed:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class SpaceshipCutscene : MonoBehaviour
{
public Transform player;
public Transform npc;
public Camera FPSCamera;
public Camera mainCamera;
public Animator anim;
public float rotationSpeed = 3f;
private bool moveNpc = false;
// Use this for initialization
void Start()
{
}
private void Update()
{
if (moveNpc)
{
Vector3 dir = player.position - npc.position;
dir.y = 0; // keep the direction strictly horizontal
Quaternion rot = Quaternion.LookRotation(dir);
// slerp to the desired rotation over time
npc.rotation = Quaternion.Slerp(npc.rotation, rot, rotationSpeed * Time.deltaTime);
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.name == "Horizontal_Doors_Kit")
{
FPSCamera.enabled = false;
mainCamera.enabled = true;
moveNpc = true;
anim.SetTrigger("SoldierAimingTrigger");
}
}
}

getting my 2d sprite flip to work depending on a Transform's location from it

So, this code just isn't responding for whatever reason. I have an enemy that I'm trying to get to face the player at all times (The enemy swoops over the player's head back and forth periodically). But other than making a flip happen whenever a timer hits 0, which doesn't really work all that well, I can't get the Flip function to work. I know the Flipper function is fine; I already tested it out and everything. I'm just not sure how to tell the enemy that when the player is to the left of it, to turn, and vice versa.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class dragoonDetection : MonoBehaviour {
private Rigidbody2D rb;
private Animator anim;
public Transform Player;
private bool facingRight = true;
void Start ()
{
rb = GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator> ();
}
void Update()
{
Flip();
}
void Flip()
{
if (Player.transform.localScale.x > 0) {
transform.localScale = new Vector3 (1.69f, 1.54f, 1f);
}
if (Player.transform.localScale.x < 0) {
transform.localScale = new Vector3 (-1.69f, 1.54f, 1f);
}
}
void Flipper()
{
facingRight = !facingRight;
Vector2 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
Got any ideas? I'd rather avoid using FindGameObject because it's not actually looking for the player script. It's looking for a child transform with no script attached to the player. And because I have two different player GameObjects that you can switch to anytime in the game, it wouldn't really work for me in that regard.
You will need to perform a check of some sort against the players position with the bird position if you want it to face the player at all times. A barebones method would just be to compare the x-positions of the two objects and change the scale accordingly.
void Update()
{
transform.localScale = new Vector3(getDir()*1.69f, 1.54f, 1);
}
private int getDir()
{
if (player.transform.position.x < transform.position.x)
return -1;
else
return 1;
}
You should throw some additional checks in here to keep it from updating the scale every frame when there is no change.

Categories