I made a code to move an enemy between 2 points, when he reaches the minimum he will stop.
I get the error because it says that the animator has no assigned variable, but I set it in the start method. It also says that and the animator will always have its default value null, I don't know what to do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAI : MonoBehaviour
{
//assigning variables
public float moveSpeed;
public Transform target;
public float chaseRadius;
public float attackRadius;
private Rigidbody2D rb;
private Animator animator;
// Start is called before the first frame update
void Start()
{
//getting the necessary components
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
CheckDistance();
}
//checking distance between 2 points and setting the rigid body to move
void CheckDistance()
{
if(Vector3.Distance(target.position, transform.position) <= chaseRadius && Vector3.Distance(target.position, transform.position) > attackRadius)
{
Vector3 temp = Vector3.MoveTowards(transform.position, target.position, moveSpeed * Time.deltaTime);
ChangeAnim(temp - transform.position);
rb.MovePosition(temp);
}
}
//changing animations of the object
private void ChangeAnim(Vector2 direction)
{
if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
{
Debug.Log("x is greater");
if(direction.x > 0)
{
animator.SetFloat("moveX", direction.x);
}
else if(direction.x < 0)
{
animator.SetFloat("moveX", direction.x);
}
}else if (Mathf.Abs(direction.x) < Mathf.Abs(direction.y))
{
Debug.Log("y is greater");
if (direction.y > 0)
{
animator.SetFloat("moveX", direction.y);
}
else if (direction.y < 0)
{
animator.SetFloat("moveX", direction.y);
}
}
}
}
Player Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed;
private Rigidbody2D myRigidbody;
private Vector3 change;
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
change = Vector3.zero;
change.x = Input.GetAxisRaw("Horizontal");
change.y = Input.GetAxisRaw("Vertical");
UpdateAnimationAndMove();
}
void UpdateAnimationAndMove()
{
if (change != Vector3.zero)
{
MoveCharacter();
animator.SetFloat("moveX", change.x);
animator.SetFloat("moveY", change.y);
animator.SetBool("moving", true);
}
else
{
animator.SetBool("moving", false);
}
}
void MoveCharacter()
{
myRigidbody.MovePosition
(
transform.position + change * speed * Time.deltaTime
);
}
}
You should add a constructor to your EnemyAI class which can be passed an animator object.
public EnemyAI(Animator animator)
{
this.animator = animator;
}
If you look at your start function in PlayerMovement you see this:
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
and your EnemyAI has this:
void Start()
{
//getting the necessary components
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
You can see the last one does not assign the animator.
Change your EnemyAI start function to this:
void Start()
{
//getting the necessary components
this.animator = animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
Related
I have a problem in unity , the player mouvement is going good until I add an animation the player stop moving even if I press the keyboard keys,when I remove the animator compenent the player move normaly without problems !
I tried separate the animation script from the movement script and still theame problem , I don't think that the problem is comming from the code
playerAnimation code :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerAnim : MonoBehaviour
{
Animator anim;
Rigidbody2D rb;
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
anim = gameObject.GetComponent<Animator>();
}
void FixedUpdate()
{
if (rb.velocity.x == 0)
anim.SetBool("isRunning", false);
else
anim.SetBool("isRunning", true);
if (rb.velocity.y > 0)
anim.SetBool("isJumping", true);
else
anim.SetBool("isJumping", false);
}
}
playerMovement script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerControl : MonoBehaviour
{
Rigidbody2D rb;
private float horizontal;
public float runSpeed;
public float jumpPower;
public bool inTheGround;
private SpriteRenderer sp;
Animator anim;
// Start is called before the first frame update
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
sp = gameObject.GetComponent<SpriteRenderer>();
anim = gameObject.GetComponent<Animator>();
}
private void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
rb.velocity = new Vector2(horizontal * runSpeed,
rb.velocity.y);
if (Input.GetButton("Jump")&& inTheGround)
{
rb.velocity = new Vector2(rb.velocity.x,jumpPower);
}
flipping();
Debug.Log(rb.velocity.x);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("ground"))
inTheGround = true;
}
private void OnCollisionExit2D(Collision2D other)
{
if
(other.gameObject.CompareTag("ground")&&rb.velocity.y>0.1)
inTheGround = false;
}
void flipping()
{
if (Input.GetKey(KeyCode.RightArrow))
sp.flipX = false;
if (Input.GetKey(KeyCode.LeftArrow))
sp.flipX = true;
}
}
Check if Apply Root Motion on Animator Component is set to false. This setting can overwrite your changes of the object's position over time. if not - can you please provide more information, perfectly a screenshot of your player components, and Animator Controller.
I am making a project in unity....
I am getting an error:
The name Vector 2 does not exist in the current context
what should I do?
my code is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class paddle : MonoBehaviour
{
Rigidbody2D rb;
public float moveSpeed;
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void TouchMove()
{
if (Input.GetMouseButton(0))
{
Vector2 touchPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(touchPos.x < 0)
{
//move left
rb.velocity = Vector2.left * moveSpeed;
}
else if(touchPos.x > 0)
{
//move right
rb.velocity = Vector2.right * moveSpeed;
}
}
else
{
rb.velocity = vector2.zero;
}
}
}
vector2.zero should probably be Vector2.zero - case matters
I was testing out scripts and there was a bug, that output 0 as its Rigidbody.velocity.y only if it goes up (so when the random chance it goes down it doesn't break), until it becomes negative (collision with resitution 1 or mirror bouncy) which then output a nonzero integer, so working as normal.
Edit: The temporary solution is just to remove the if statement in if (rb.velocity.y != 0) but i wanna know why does it output 0
Edit2: Maybe its a Unity bug, and i am in Unity 2019.4, so updating might be the solution? So if the "bug" dissapears, im sorry for wasting your time
First code determines the ball, while the second determines the ai
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallMovement : MonoBehaviour
{
public float speed;
public Rigidbody2D rb;
public Vector3 startPosition;
public float rampSpeed;
private float startSpeed;
public float tempSpeed;
// Start is called before the first frame update
void Start()
{
startPosition = transform.position;
startSpeed = speed;
Launch();
}
// Update is called once per frame
void Update()
{
}
private void Launch()
{
float x = Random.Range(0,2) == 0 ? -1 : 1;
float y = Random.Range(0,2) == 0 ? -1 : 1;
rb.velocity = new Vector2(speed * x, speed * y);
}
private void OnCollisionEnter2D ()
{
tempSpeed = speed;
speed += rampSpeed;
rb.velocity = new Vector2(rb.velocity.x*speed/tempSpeed,rb.velocity.y*speed/tempSpeed);
GetComponent<AudioBall>().SoundCollision();
}
public void Reset()
{
rb.velocity = Vector2.zero;
transform.position = startPosition;
speed = startSpeed;
Launch();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public bool isPlayer1;
public float speed;
public float moveInput;
private Rigidbody2D rb;
public Vector3 startPosition;
//AI
[Header("Ball")]
public GameObject ball;
private Rigidbody2D rbBall;
private float sign;
public bool ActivateAI;
public bool TurnOnOveride;
// Start is called before the first frame update
void Start()
{
if (TurnOnOveride == false)
{
ActivateAI = PlayMenu.ActivateAI;
}
else
{
ActivateAI = true;
}
startPosition = transform.position;
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if(ActivateAI == false || isPlayer1 == true)
{
//this part is just human control. dont mind this
if (isPlayer1 == true)
{
moveInput = Input.GetAxisRaw("Vertical");
}
else
{
moveInput = Input.GetAxisRaw("Vertical2");
}
}
//AI
else
{
rbBall = ball.GetComponent<Rigidbody2D>();
sign = Mathf.Sign(rbBall.velocity.y);
Debug.Log("sign:"+sign);
if (sign == -1)
{
moveInput = -1;
}
else
{
Debug.Log("rb.y:"+rb.velocity.y);
if (rb.velocity.y != 0)
{
moveInput = 1;
}
}
}
rb.velocity = new Vector2(rb.velocity.x, moveInput * speed);
}
public void Reset()
{
rb.velocity = Vector2.zero;
transform.position = startPosition;
}
}
I started making a 2D game in Unity and I have a problem with my player. I add 2 buttons for left and right and jump just tapping the display . When I start the game just the buttons left and right works and the jump don't . I added from another script something for jump and now when I start the game the player goes automatically at right and don't respect the buttons action. (but jumping works) this is the 2 codes that I joined them :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public float moveSpeed = 300;
public GameObject character;
private Rigidbody2D characterBody;
private float ScreenWidth;
void Start()
{
ScreenWidth = Screen.width;
characterBody = character.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
int i = 0;
while (i < Input.touchCount)
{
if (Input.GetTouch(i).position.x > ScreenWidth / 2)
{
RunCharacter(1.0f);
}
if (Input.GetTouch(i).position.x < ScreenWidth / 2)
{
RunCharacter(-1.0f);
}
++i;
}
}
void FixedUpdate()
{
#if UNITY_EDITOR
RunCharacter(Input.GetAxis("Horizontal"));
}
private void RunCharacter(float horizontalInput)
{
characterBody.AddForce(new Vector2(horizontalInput * moveSpeed * Time.deltaTime, 0));
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move2d : MonoBehaviour
{
public float playerSpeed; //allows us to be able to change speed in Unity
public Vector2 jumpHeight;
public bool isDead = false;
private Rigidbody2D rb2d;
private Score gm;
// Use this for initialization
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
gm = GameObject.FindGameObjectWithTag("gameMaster").GetComponent<Score>();
}
// Update is called once per frame
void Update()
{
if (isDead) { return; }
transform.Translate(playerSpeed * Time.deltaTime, 0f, 0f); //makes player run
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpHeight, ForceMode2D.Impulse);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("ground")) // this will return true if the collision gameobject has ground tag on it.
{
isDead = true;
rb2d.velocity = Vector2.zero;
GameController.Instance.Die();
}
}
void OnTriggerEnter2D(Collider2D col)
{
if( col.CompareTag("coin"))
{
Destroy(col.gameObject);
gm.score += 1;
}
}
}
If you know a better script please help
Try adding #endif for the #if UNITY_EDITOR
I get the null reference exception error when trying to change the boolean to right (or left in that regard). My prefab should spawn at FirepointL.
My script does recognise the prefeb as it does not return a Null for finding the prefab (tested this).
I made sure my boolean was set to Public and i had dropped all the GameObjects to their designated places in the Inspector.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public GameObject bullet;
private Rigidbody2D myRigidbody;
private float speed = 15;
private bool facingRight;
private bool ground = false;
private float jump = 23;
// Start is called before the first frame update
void Start()
{
facingRight = true;
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
bullet = GameObject.FindGameObjectWithTag("Button");
Movement(horizontal);
Flip(horizontal);
if (Input.GetKey("w"))
{
if (ground)
{
GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, jump);
}
}
// this is the part that returns the error
if (facingRight == true)
{
bullet.GetComponent<weapon>().right = true;
}
if (facingRight == false)
{
bullet.GetComponent<weapon>().right = false;
}
}
void OnTriggerEnter2D()
{
ground = true;
}
void OnTriggerExit2D()
{
ground = false;
}
private void Movement(float horizontal)
{
myRigidbody.velocity = new Vector2(horizontal * speed,myRigidbody.velocity.y);
}
private void Flip(float horizontal)
{
if (horizontal > 0 && !facingRight || horizontal < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class weapon : MonoBehaviour
{
// Start is called before the first frame update
public bool right;
public Transform firepointR;
public Transform firepointL;
public GameObject bulletPrefab;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown("space"))
{
Debug.Log("It's the space key");
Shoot();
}
}
void Shoot()
{
if (right == true)
{
Instantiate(bulletPrefab, firepointR.position, firepointR.rotation);
}
if(right == false)
{
Instantiate(bulletPrefab, firepointL.position, firepointL.rotation);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bullet : MonoBehaviour
{
public float speed = 20;
public Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb.velocity = transform.right * speed;
}
// Update is called once per frame
void Update()
{
}
}
Not sure if it's the exact issue, but there's a problem in PlayerMovement class. When you retrieve bullet you assume that an object with Button tag is present.
In my opinion, you should check for it with
// this is the part that returns the error
if (bullet && facingRight == true)
{
bullet.GetComponent<weapon>().right = true;
}
if (bullet && facingRight == false)
{
bullet.GetComponent<weapon>().right = false;
}
I think there is a problem with naming conventions. You are trying to find out a bullet whose name is "Button" but when you are instantiating the gameobject, it names it to something like Button(clone).
One solution that comes in my mind:
1st step:
Make a public static variable inside PlayerMovement script.
public static PlayerMovement Instance;
private void Awake()
{
Instance = this;
}
Set its value inside the awake function so that you can call it from anywhere.
2nd step:
I modified the shoot function.
void Shoot()
{
GameObject _firePosition = right == true ? firepointR : firepointL;
PlayerMovement.Instance.bullet = Instantiate(bulletPrefab, _firePosition.position, _firePosition.rotation); // we are setting the reference on runtime whenever we spawn a new bullet.
}
3rd Step:
Remove this line from PlayerMovement script as it is not needed now.
bullet = GameObject.FindGameObjectWithTag("Button");
PS: Code will not work if you don't follow step 3. Let me know if it helps. :)