Unity "Unassigned Reference Exception" - c#

I'm super new to coding and to this forum so forgive me if I break any taboo's here. I'm simply working on a 3rd person camera, just kind of messing around but I keep getting
UnassignedReferenceException: The variable CameraFollowObj of CameraFollow has not been assigned.
You probably need to assign the CameraFollowObj variable of the CameraFollow script in the inspector.
CameraFollow.CameraUpdater () (at Assets/Scripts/CameraFollow.cs:68)
CameraFollow.LateUpdate () (at Assets/Scripts/CameraFollow.cs:62)"
I've created an object for my camera to follow and placed it on the model. Then moved the object to what I believe to be the correct field but the issue still persists.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public float CameraMoveSpeed = 120.0f;
public GameObject CameraFollowObj;
Vector3 FollowPOS;
public float clampAngle = 80.0f;
public float InputSensitivity = 150.0f;
public GameObject CameraObj;
public GameObject PlayerObj;
public float camDistanecXToPlayer;
public float camDistanecYToPlayer;
public float camDistanecZToPlayer;
public float mouseX;
public float mouseY;
public float finalInputX;
public float finalInputZ;
public float smoothX;
public float smoothY;
private float rotY = 0.0f;
private float rotX = 0.0f;
// Start is called before the first frame update
void Start()
{
Vector3 rot = transform.localRotation.eulerAngles;
rotY = rot.y;
rotX = rot.x;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
float InputX = Input.GetAxis("RightStickHorizontal");
float InputZ = Input.GetAxis("RightStickVertical");
mouseX = Input.GetAxis("Mouse X");
mouseY = Input.GetAxis("Mouse Y");
finalInputX = InputX + mouseX;
finalInputZ = InputZ + mouseY;
rotY += finalInputX * InputSensitivity * Time.deltaTime;
rotX += finalInputZ * InputSensitivity * Time.deltaTime;
rotX = Mathf.Clamp(rotX, -clampAngle, clampAngle);
Quaternion localRotation = Quaternion.Euler(rotX, rotY, 0.0f);
transform.rotation = localRotation;
}
void LateUpdate()
{
CameraUpdater();
}
void CameraUpdater()
{
Transform target = CameraFollowObj.transform;
float step = CameraMoveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards (transform.position, target.position, step);
}
}

Make sure you haven't added the script to another gameobject somewhere else in the project that might cause this error.
You can search for the script in the scene search bar and all the gameObjects with the script attached will appear. Also in runtime if you right click on the script and in the contextual menu you select option kind of "find all the references in the scene" or something similar, you get all the instances of the script in your scene.
I think you should have drargged the script into another gameObject by mistake where the cameraToFollow gameObject is empty so you get the unnasigned error.
Hope this helps.

There are multiple things you can try to do:
Make sure you dragged the correct object in the field (I doubt that your character object is called CameraFollow)
Make sure that you dragged in an object from the Hierarchy and not the Assets window (ethats means that you need to drag in objects that are currently in the scene and can be seen on the hierarchy)
If you try everything from above and it doesen't work try assigning the object in the start function of the script. You can use GameObject.Find
Hope this helped to clarify a few things for you. Now if you really want to create a top level camera system you can also check this video out. Its an example of how to make a third person camera with the Cinemachine component (comes with Unity package manager for free)
I wish you luck with coding in Unity and welcome to the community :)

Related

Player moves at a very slow speed in Unity

I'm making a first-person movement script for the player, and everything movement-wise seems to work fine (other than an unrelated issue of the player not moving in the camera's direction), however when running in the game, the player moves at a very slow speed.
Here's the movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Rigidbody RB;
[SerializeField] private GameObject cam;
private float walkVel; // Forward & backward movement
private float strafeVel; // Sideways movement
[SerializeField] public float walkSpeed = 5f;
private void Start()
{
RB = GetComponent<Rigidbody>();
}
private void Update()
{
walkVel = Input.GetAxis("Vertical");
strafeVel = Input.GetAxis("Horizontal");
}
private void FixedUpdate()
{
transform.localRotation = Quaternion.Euler(0f, cam.transform.rotation.y * Time.deltaTime, 0f);
Vector3 Up = new Vector3(RB.velocity.x, RB.velocity.y, RB.velocity.z);
RB.velocity = (transform.forward * strafeVel + transform.right * walkVel).normalized * walkSpeed * Time.deltaTime;
}
}
I'm pretty sure the issue is not related to the camera script, but here it is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCamPositioning : MonoBehaviour
{
private Vector2 camTurn;
[SerializeField] public float camSensitivity = 5f;
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
private void Update()
{
camTurn.x += Input.GetAxis("Mouse X") * camSensitivity;
camTurn.y -= Input.GetAxis("Mouse Y") * camSensitivity;
transform.localRotation = Quaternion.Euler(camTurn.y, camTurn.x, 0);
}
}
I tried to implement a very basic velocity script, and alternatively RB.AddVelocity to the Rigidbody, however it did not solve my problem.
I also tried simply increasing the walkSpeed variable to increase player speed, which actually solves my problem, HOWEVER I want to refrain from using this solution as previously the player moved at a relatively normal speed with walkSpeed set to 5f.
Sounds like you just need to tweak your values. Try splitting your equation into pieces and logging the individual and multiplied value so you can understand what values you see versus what values you're expecting.
I see many variables in your code that can be less than 1. strafeVel, walkVel and Time.deltaTime. In fact, in my experience, Time.deltaTime is always a very small float.
Perhaps you would prefer to use RB.velocity with += or *= along with a Mathf.Clamp() to gradually increase your speed.
All I had to do to solve my problem was remove Time.deltaTime from the RB.Velocity vector. The vector already runs in the FixedUpdate function, so I think it should work as intended now.

Set rigidbody.velocity to direction of mouse in Unity2d: Updated Version

Yes I know this question was asked before by SuperSonyk! That post is here:
Set rigidbody.velocity to direction of mouse in Unity2d
However- the link referenced in the answer to that post is now legacy material, and I can't bring myself to understand it in Unity's current version.
My Problem: In short, I want to make my player accelerate in the direction of my cursor. My game is currently a TOP-DOWN Space Shooter in 2D. My player already looks at my mouse correctly, using cam.ScreenToWorldPoint. But relentlessly trying to add force seems futile for me, since I am fairly new to coding.
If I have any other issues in my code, It would be great if anyone could point them out!
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//================= MOVEMENT =====================
private float thrust = 0.5f;
private float maxSpeed = 10f;
public Rigidbody2D rb;
//================= AIMING =======================
public Camera cam;
Vector2 mousePos;
// Update is called once per frame: Good for INPUTS
void Update()
{
//aiming
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
}
// Called Set amount of times. Good for PHYSICS CALCULATIONS
void FixedUpdate()
{
Move();
speedLimiter();
//aim
Vector2 lookDirection = mousePos - rb.position;
float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
}
//======= MY MOVE FUNCTION DOES NOT WORK. HELP? ======
void Move()
{
if (Input.GetButtonDown("Accelerate"))
{
rb.velocity = new Vector3(0, thrust, 0) * Time.deltaTime;
}
}
void speedLimiter()
{
if (rb.velocity.magnitude > maxSpeed)
{
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
}
}
}
Please summarize the edits clearly, thank you!
In general since this is a 2D rigidbody also the velocity is a Vector2 and you should probably rather use Vector2.ClampMagnitude
and then in
rb.velocity = new Vector3(0, thrust, 0) * Time.deltaTime;
do you only want to move in global Y direction? Also a velocity is already a "per second" value -> it makes no sense to multiply by Time.deltaTime if you reassign a new velocity. Since it says thrust I guess you rather wanted to add to the existing velocity.
What you would rather do is save your mouse direction you already have and do
public class PlayerController : MonoBehaviour
{
...
void FixedUpdate()
{
// I would update the aim BEFORE moving
// Use a NORMALIZED direction! Makes things easier later
Vector2 moveDirection = (mousePos - rb.position).normalized;
float angle = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
// OPTIONAL: Redirect the existing velocity into the new up direction
// without this after rotating you would still continue to move into the same global direction
rb.velocity = rb.velocity.magnitude * moveDirection;
Move(moveDirection);
speedLimiter();
}
void Move(Vector2 moveDirection)
{
if (Input.GetButtonDown("Accelerate"))
{
// Instead of re-assigning you would probably add to the existing velocity
// otherwise remove the "+" again
rb.velocity += moveDirection * thrust * Time.deltaTime;
}
}
void speedLimiter()
{
if (rb.velocity.magnitude > maxSpeed)
{
// You are working with Vector2 so use the correct method right away
rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);
}
}
}
You already have half of the work by having your player looking at the mouse. We will be using the vector lookDirection as the direction of the movement for the player, normalize it so its length is 1 and multiply it by thrust. This way, we have a vector in the direction of the mouse and of length thrust as intended.
void Move()
{
if (Input.GetButtonDown("Accelerate"))
{
Vector2 lookDirection = (mousePos - rb.position);
rb.AddForce(lookDirection.normalized * thrust);
}
}
Note that we work here with Vector2 since you are using a Rigidbody2D.
Also, I don't think that using Time.DeltaTime is relevant here. When you apply force to a physic object, you don't need to use it, by definition, the function FixedUpdate() has a fixed frequency. If you look at one of Unity's tutorial, you can see that they don't multiply it by Time.DeltaTime
Last tip: you may want to be playing around with the drag property of your Rigidbody2D to have your player slow down over time when not accelerating, otherwise, it will be sliding out of control and the player won't be able to stop it.
Don't hesitate to tell me if my answer is not clear for you or does not entirely satisfy you, it's my first answer here!
EDIT: I forgot to tell you but as derHugo mentioned, since you are using Rigidbody2D, you must use Vector2.ClampMagnitude to limit your speed in your speedLimiter function. Also, I don't think that you need your if since the function Vector2.ClampMagnitude will only change the value of the velocity if it exceeds the maximum.
Thanks to everyone who responded!
With the help of Brackeys community, I managed to solve this by using this method:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//================= MOVEMENT =====================
private float thrust = 10f;
private float maxSpeed = 100f;
public Rigidbody2D rb;
//================= AIMING =======================
public Camera cam;
Vector2 mousePos;
// Update is called once per frame: Good for INPUTS
void Update()
{
//aiming
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
}
// Called Set amount of times. Good for PHYSICS CALCULATIONS
void FixedUpdate()
{
Move();
speedLimiter();
//aim
Vector2 lookDirection = mousePos - rb.position;
float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
}
void Move()
{
if (Input.GetKey("up"))
{
rb.AddRelativeForce(Vector2.up*thrust);
}
}
void speedLimiter()
{
if (rb.velocity.magnitude > maxSpeed)
{
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
}
}
//rb.AddForce(new Vector3(0, thrust, 0));
}

Moving child GameObject inside moving parent GameObject

I am trying to make a 2.5D SHMUP type game in which the world continuously moves forward while the player's spaceship and camera stay in place. This means that even if the world is moving, if the player's ship is in the middle of the screen it will stay there.
To do this I've created an empty game object named Moving World and attached the following script to it:
public class movingWorldController : MonoBehaviour
{
private float movementSpeed = 5f;
void Update()
{
transform.position = transform.position + new Vector3(0, 0, movementSpeed * Time.deltaTime);
}
}
I then added the camera and spaceship as children to of this object, and as a result they indeed move with the moving world object. However, I also have a script attached to the spaceship to allows it to move according to the player's input, and if I enable the script above the ship stops responding to the player's input. The ship's script looks like this:
public class ShipController : MonoBehaviour
{
public Rigidbody rb;
public float moveSpeed = 5f;
private Vector3 movement;
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.z = Input.GetAxisRaw("Vertical");
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + movement * moveSpeed * Time.deltaTime);
}
}
The ship controller works just fine when the world-moving script is disabled, so I suspect the world script is somehow overwriting the spaceship position. How may I solve this?
For a POC example see this video: https://www.youtube.com/watch?v=-fVjWgfUKn4&t=282s (jump to 4:00 to see the game in action). Note that in the video gamemaker is used to achieve the effect, while I am trying to achieve a similar effect using just code.
I achieved the effect I was aiming for by doing the following. First, I removed the MovingWorld object and instead applied the following script to the camera:
public class movingWorldController : MonoBehaviour
{
public float movementSpeed = 5f;
void FixedUpdate()
{
transform.position = transform.position + new Vector3(0, 0, movementSpeed * Time.deltaTime);
}
}
This will cause the camera to continuously move forward. Next, to make sure the player's ship keeps up with the camera, and is maneuverable at the same time, I applied the following script to the ship's object:
public class ShipController : MonoBehaviour
{
public Rigidbody rb;
private float shipVelocity = 5f;
public float moveSpeed = 10f;
private Vector3 movement;
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal") * moveSpeed;
movement.z = Input.GetAxisRaw("Vertical") * moveSpeed + shipVelocity;
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + movement * Time.deltaTime);
}
}
Two important notes:
The shipVelocity variable was introduced to make sure the ship continues to cruise at camera-speed.
Even though the camera is not a RigidBody its position update must occur during the FixedUpdate method to make sure it moves on the same frame as the ship. Updating it using the Update method will introduce jittering to the ship due to de-synchronization.

Is there a easy way to make a movement script for 2d unity game?

I need help with C# in Unity. I know C# pretty well but don't know the C# UnityEngine namespace.
Unity doesn't support enough movement script's for and since I don't know how to use C# for Unity, I don't want o try editing the main code.
Any code using this namespace I am confused with:
using UnityEngine;
and I am confused with variables like this:
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
here is a simple 2d caracter movement controller. In order for this script to work, you must:
1. Assign this script to your caracter.
2. Add a RigidBody2d to your caracter.
3. Assign a value at the speed and jumpHeight variables from the inspector of your caracter.
public float speed;
public float jumpHeight;
Rigidbody2D rb;
void Start(){
//Get the rigidbody2d of the gameObject this script is assigned to.
rb = GetComponent<Rigidbody2D>();
}
void Update() {
//Determine the direction of the movement based on user input.
float moveDir = Input.GetAxis("Horizontal");
//Calculate the velocity of the gameObject.
rb.velocity = new Vector2(moveDir * speed, rb.velocity.y);
// Your jump code:
if (Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
}
}
Hope this works for you. If you need more help, check unity's official turtorials.

Issues with a script that should follow another GameObject's position

I currently have a little issue with a script I made. Basically, I want to create a script that makes its GameObject (let's name it A) and follows another GameObject's (named B) position. I know a simple way to do that would be to parent A to B, but I'm not doing it for two reasons :
1) I want to be able to apply a smoothing (whose value I can change) on A's movement;
2) I want to be able to make A follow B's position and/or rotation at will.
Here is the script I wrote :
using UnityEngine;
using System.Collections;
public class FollowGameObject : MonoBehaviour {
public GameObject m_GameObjectToFollow;
public bool m_FollowPosition;
public bool m_FollowRotation;
public float m_PositionSmoothing;
public float m_RotationSmoothing;
// Should not be changed once set
public bool m_UseOffsetPosition;
public bool m_UseOffsetRotation;
private Vector3 m_PositionOffset;
private Quaternion m_RotationOffset;
void Start () {
m_PositionSmoothing = Mathf.Clamp(m_PositionSmoothing, 0.0f, 1.0f);
m_RotationSmoothing = Mathf.Clamp(m_RotationSmoothing, 0.0f, 1.0f);
if (m_UseOffsetPosition)
{
m_PositionOffset = transform.position - m_GameObjectToFollow.transform.position;
} else {
m_PositionOffset = Vector3.zero;
}
if (m_UseOffsetRotation)
{
m_RotationOffset = transform.rotation * Quaternion.Inverse(m_GameObjectToFollow.transform.rotation);
} else {
m_RotationOffset = Quaternion.identity;
}
}
void FixedUpdate () {
if (m_FollowPosition) {
Vector3 goalPosition = m_GameObjectToFollow.transform.position + m_PositionOffset;
transform.position = Vector3.Lerp(transform.position, goalPosition, m_PositionSmoothing);
//transform.Translate(newPosition - transform.position, Space.World);
}
if (m_FollowRotation) {
Quaternion goalRotation = m_GameObjectToFollow.transform.rotation * m_RotationOffset;
transform.rotation = Quaternion.Lerp(transform.rotation, goalRotation, m_RotationSmoothing);
}
}
I hope the code is easily understandable, if not feel free to ask.
In any case, once I attach this script to A and assign its m_GameObjectToFollow attribute to B (B is parented to a character controller, and I parented a sphere renderer to A so I can see if it follows B correctly), I notice that A is indeed following B, but I see that its position (through the sphere renderer) is "fluctuating" between the "right" position (B's) and another one. Visually, the sphere is flickering.
I tried putting the smoothing values to 1 (i.e. A should always be at B's position/rotation). I still see a flickering.
Could someone explain to me what I did wrong?
EDIT : Seems like I'm using Lerp the wrong way with its last value. I modified the script to use speed values instead of smoothing values, but still the same problem when I try to create some smooth movements (with lower speed values).
I have troubles explaining the problem properly. The best way to see what the problem look like would be to experience it yourself :
1) Create a scene with a terrain and a character controller in it;
2) Parent the main camera to the controller (so that it always follows it);
3) Create a new GameObject with a renderer (for example, a sphere), not parented to any other GameObject, but attach the following script to it :
using UnityEngine;
using System.Collections;
public class FollowGameObject : MonoBehaviour {
public GameObject m_GameObjectToFollow;
public bool m_FollowPosition;
public bool m_FollowRotation;
// Betzeen 0 and 1. 1 means that a complete unsmoothed follow
public float m_PositionFollowSpeed;
public float m_RotationFollowSpeed;
// Should not be changed once set
public bool m_UseOffsetPosition;
public bool m_UseOffsetRotation;
private Vector3 m_PositionOffset;
private Quaternion m_RotationOffset;
void Start () {
if (m_UseOffsetPosition)
{
m_PositionOffset = transform.position - m_GameObjectToFollow.transform.position;
} else {
m_PositionOffset = Vector3.zero;
}
if (m_UseOffsetRotation)
{
m_RotationOffset = transform.rotation * Quaternion.Inverse(m_GameObjectToFollow.transform.rotation);
} else {
m_RotationOffset = Quaternion.identity;
}
}
void Update () {
if (m_FollowPosition) {
Vector3 goalPosition = m_GameObjectToFollow.transform.position + m_PositionOffset;
transform.position = Vector3.Slerp(transform.position, goalPosition, Time.deltaTime * m_PositionFollowSpeed);
}
if (m_FollowRotation) {
Quaternion goalRotation = m_GameObjectToFollow.transform.rotation * m_RotationOffset;
transform.rotation = Quaternion.Slerp(transform.rotation, goalRotation, Time.deltaTime * m_RotationFollowSpeed);
}
}
}
With :
m_GameObjectToFollow = the character controller GameObject;
m_FollowPosition = true;
m_PositionFollowSpeed = 10;
(The other parameters values don't matter for this test)
Now start the scene and move the character controller, I will see the sphere flickering during motion, but if you stop moving it will smoothly go to the controller.
You are using FixedUpdate. Is there any special reason to do so?
Anyway, try to use Update or LateUpdate instead of FixedUpdate or check Fixed Timestep in Project Settings => Time.
Also read the answer to this question for more information about difference between Update and FixedUpdate.

Categories

Resources