I am getting the error The name mainCamera' does not exist in the current context for the linetargetPos = (Vector2)mainCamera.main.ScreenToWorldPoint(Input.mousePosition);`. I have search for an answer but cannot find a way to stop this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
float speed = 2f;
Vector2 targetPos;
private Rigidbody2D myRigidbody;
private Animator myAnim;
private static bool playerExists;
public GameObject cameraPrefab;
private void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
myAnim = GetComponent<Animator>();
if(!playerExists){
playerExists = true;
DontDestroyOnLoad(transform.gameObject);
} else {
Destroy(gameObject);
}
targetPos = transform.position;
GameObject mainCamera = (GameObject)Instantiate(cameraPrefab);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
targetPos = (Vector2)mainCamera.main.ScreenToWorldPoint(Input.mousePosition);
}
if ((Vector2)transform.position != targetPos)
{
Move();
} else {
myAnim.SetBool("PlayerMoving", false);
}
}
You're getting that particular error because mainCamera is a local variable defined in Start. It is out of scope where you try to reference it in Update. You probably meant to define it as a field in your class, so you could reference it with mainCamera anywhere in your class. To do that you should do this instead:
// ...
private Rigidbody2D myRigidbody;
private Animator myAnim;
private static bool playerExists;
public GameObject cameraPrefab;
public GameObject mainCamera; // add this line
private void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
myAnim = GetComponent<Animator>();
if(!playerExists){
playerExists = true;
DontDestroyOnLoad(transform.gameObject);
} else {
Destroy(gameObject);
}
targetPos = transform.position;
mainCamera = (GameObject)Instantiate(cameraPrefab); // use mainCamera field
mainCamera.tag = "MainCamera"; // tell Unity that it is your main camera.
}
// ...
But anyway, Camera.main is a static property of the Camera class, so you should access it through the Camera class anyway.
You should use this in Update instead:
targetPos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
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 have just started a new Unity tut using its input system to move a ball. However, the script doesn't seem to be working when I try to move the ball
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem; //Namespace for accessing InputSystem to control ball
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
private float movementX;
private float movementY;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Onmove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
void FixedUpdate()
{
Vector3 movement = new Vector3(movementX, 0.0f, movementY);
rb.AddForce(movement);
}
}
If you did everything else right and the problem is only in your script then changing from Onmove to OnMove should fix problem
Create in Unity a new InputControl with the name PlayerInputActions and into
Inspector select Generate C# class, Unity autogenerate for you Action Maps , Actions and Binding Property, double click on it to watch, than in a new c# script named NewInputSystem
using UnityEngine;
using UnityEngine.InputSystem;
public class NewInputSystem : MonoBehaviour
{
public Rigidbody rb;
public float moveSpeed = 7.0f;
Vector2 moveDirections = Vector2.zero;
public PlayerInputActions playerControls;
private InputAction move;
private void Awake()
{
playerControls = new PlayerInputActions();
}
private void OnEnable()
{
move = playerControls.Player.Move;
move.Enable();
}
private void OnDisable()
{
move.Disable();
}
void Start()
{
rb =gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
moveDirections = move.ReadValue<Vector2>();
}
private void FixedUpdate()
{
//change how you want
rb.velocity = new Vector3(moveDirections.y * moveSpeed, 0, moveDirections.x * -moveSpeed);
}
}
I'm working on some animations for a game I'm working on (Still in the very early stages, and new to coding). Right now I'm trying to use a bool to detect whether or not the player is jumping, and then if it returns true, then the animation will play.
Character Controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character2dController : MonoBehaviour
{
public float MovementSpeed = 8;
public float JumpForce = 5;
public Transform feet;
public bool isJumping;
private Rigidbody2D rb;
public LayerMask groundLayers;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
isJumping = false;
}
// Update is called once per frame
void Update()
{
Jump();
//LR movement
var movement = Input.GetAxis("Horizontal");
transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * MovementSpeed;
isJumping = false;
}
//Jumping
void Jump()
{
if (Input.GetButtonDown("Jump") && IsGrounded())
{
isJumping = true;
rb.AddForce(new Vector2(0, JumpForce), ForceMode2D.Impulse);
}
}
//Grounding
public bool IsGrounded()
{
Collider2D groundCheck = Physics2D.OverlapCircle(feet.position, 0.5f, groundLayers);
if (groundCheck.gameObject != null)
{
return true;
}
return false;
}
}
CharacterAnimation:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterAnimation : MonoBehaviour
{
private Animator anim;
private bool isJumping;
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
isJumping = GetComponent<Character2dController>().isJumping;
isJumping = false;
}
// Update is called once per frame
void Update()
{
//Walking Anim
if (Input.GetKey("a") || Input.GetKey("d"))
{
anim.SetBool("isWalking", true);
}
else
{
anim.SetBool("isWalking", false);
}
//Character flipping
if (Input.GetKey("a"))
{
transform.localScale = new Vector3(-1, 1, 1);
}
if (Input.GetKey("d"))
{
transform.localScale = new Vector3(1, 1, 1);
}
if(isJumping == true)
{
anim.SetTrigger("Up");
}
}
}
However, the isJumping bool never seems to change to true, and thus the animation will never play. I've tried putting it in a variety of places within the character controller code, but none of them seem to work. I'm wondering if there's something I'm doing wrong or if I should just use a different way to animate the player jumping.
Again I'm fairly new to coding so if there's anything that's wrong feel free to let me know. Thanks!
public class CharacterAnimation : MonoBehaviour
{
private Animator anim;
private bool isJumping;
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
isJumping = GetComponent<Character2dController>().isJumping;//assigns value
isJumping = false;
}
.
.
.
The line that I commented only assigns the value of isJumping variable in the Character2dController class, to the isJumping variable in your CharacterAnimation class. Therefore when you change the isJumping variable in the Character2dController class, the isJumping variable in the CharacterAnimation class is not updated.
So instead, you could check the isJumping variable from the Character2dController class:
public class CharacterAnimation : MonoBehaviour
{
private Animator anim;
private Character2dController character2dController;
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
character2dController = GetComponent<Character2dController>();//now we are holding a reference to the Character2dController component
}
// your other code here
if(character2dController.isJumping == true)
{
anim.SetTrigger("Up");
}
Also, in the Character2dController, you are setting isJumping to false at every frame, which is I believe not what you want to do. Instead of setting it directly to false, you should check whether you are grounded or not, and update the isJumping accordingly.
Try to get inputs with Keycode. like this:
if (Input.GetKey(KeyCode.A)) {
Debug.LogError("A");
}
You can try to Debug.LogError("Message on key pressed") to be sure you are capturing the input.
If you are sure you are capturing your input properly you can indicate that in your question so that a possible helper knows that to dive deep into the code.
Also post any console error you might be getting.
Also be sure that the parameters that control the animation are set, for example in the anim.SetBool("isWalking", true); you are able to check in the editor itself if setting the parameter the animation takes place.
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>();
}
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. :)