I'm working on Stealth tutorial on Unity5. While I was writing the "Alarm Light" script, this error showed up
Assets/AlarmLight.cs(28,31): error CS0120: An object reference is required to access non-static member `UnityEngine.Light.intensity'
Here is the entire script;
using UnityEngine;
using System.Collections;
public class AlarmLight : MonoBehaviour {
public float fadeSpeed = 2f;
public float highIntensity = 2f;
public float lowIntensity = 0.5f;
public float changeMargin = 0.2f;
public bool alarmOn;
private float targetIntensity;
void Awake(){
GetComponent<Light>().intensity = 0f;
targetIntensity = highIntensity;
}
void Update()
{
if (alarmOn) {
GetComponent<Light>().intensity = Mathf.Lerp (GetComponent<Light>().intensity, targetIntensity, fadeSpeed * Time.deltaTime);
CheckTargetIntensity ();
}
else
{
Light.intensity = Mathf.Lerp (GetComponent<Light>().intensity, 0f, fadeSpeed * Time.deltaTime);
}
}
void CheckTargetIntensity (){
if (Mathf.Abs (targetIntensity - GetComponent<Light>().intensity) < changeMargin) {
if (targetIntensity == highIntensity) {
targetIntensity = lowIntensity;
}
else {
targetIntensity = highIntensity;
}
}
}
}
Basically, what the compiler is telling you is that you're trying to use an instance member like a static member, which obviously, is incorrect.
Look at this line in your code
else {
Light.intensity = Mathf.Lerp (GetComponent<Light>().intensity, 0f, fadeSpeed * Time.deltaTime);
}
On the right hand side, you use GetComponent<Light>().intensity, which is the correct way of accessing a single Light's intensity.
On the LEFT hand side, however, you're using Light.intensity. The Light class does not have any static member named intensity, and hence the error.
Change your code to
else {
GetComponent<Light>().intensity = Mathf.Lerp (GetComponent<Light>().intensity, 0f, fadeSpeed * Time.deltaTime);
}
and your error should go away.
Think about it this way. You can change the intensity of each of your lights seperately, correct? Therefore, it MUST be a member of an instance of the class, rather than the class itself.
If changing a single value effects everything that uses it, (such as Physics.gravity), then those are static members of the class. Keep that in mind, and you won't have this issue pop up.
Related
So essentially I've:
Instantiated a new prefab of an object
Set all the variables in the transform of the prefab
Copied the script for the initial capsule (which works) into the prefab spawning script
And yet my prefabs for some reason really do not want to follow the path around, how do I make them follow the path?
public class PathFollower : MonoBehaviour
{
public float movementSpeed;
//private float pathProgress = 0;
public GameObject objectToSpawn;
public Transform[] positionPoint;
[Range(0,1)]
public float value;
void Start()
{
Debug.Log(iTween.PathLength(positionPoint));
}
void Update()
{
movementSpeed = 10f;
if (value < 1)
{
value += Time.deltaTime / movementSpeed;
}
iTween.PutOnPath(objectToSpawn, positionPoint, value);
}
private void OnDrawGizmos()
{
iTween.DrawPath(positionPoint,Color.green);
}
}
public class deployCapsule : MonoBehaviour
{
public float movementSpeed;
public Transform[] positionPoint;
public GameObject CapsulePrefab;
[Range(0, 1)]
public float value;
//movementspeed = 10f;
// Start is called before the first frame update
void Start()
{
}
void Update()
{
GameObject a = Instantiate(CapsulePrefab) as GameObject;
a.transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width - 20, Screen.height - 20, 10));
//if (Input.GetKeyDown(KeyCode.Space))
//{
a.GetComponent<PathFollower>().positionPoint = positionPoint;
//}
movementSpeed = 10f;
if (value < 1)
{
value += Time.deltaTime / movementSpeed;
}
iTween.PutOnPath(a, positionPoint, value);
}
}
Where the scripts are attached, also shows transform arrays:
Hard to say what is the exact problem, but from the image no 3 I see that value of variable value is 1 which may cause the problem.
It should be 0 so the object is at the beginning of the path.
You can use Start method to explicitly set the value of the value variable
Despite this, I wouldn't recommend you to instantiate game objects every frame (in Update method) because it's not efficient and probably will never have such use case.
Every time I add an argument to my parameter in Character.cs which is basically trying to create an object of a class that uses an interface so that I can use the methods of said class to implement a function:
Lmovements left = ScriptableObject.CreateInstance<Lmovements>(position);
I get the error:
No overload for method 'CreateInstance' takes 1 argument
This is my code:
Lmovements.cs:
public class Lmovements : ScriptableObject, Commandclass.Execute
{
Vector3 cdirection;
float speed = 3f;
public Lmovements(Vector3 direction)
{
cdirection = direction;
}
public void Execute()
{
cdirection.x += speed * Time.deltaTime;
}
}
Character.cs:
public class Character : MonoBehaviour
{
float speed = 3f;
void Update()
{
Vector3 position = transform.position;
if (Input.GetKey(KeyCode.LeftArrow))
{
//position.x += speed * Time.deltaTime;
Lmovements left = ScriptableObject.CreateInstance<Lmovements>(position);
left.Execute();
}
if (Input.GetKey(KeyCode.RightArrow))
{
position.x -= speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.UpArrow))
{
position.z -= speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.DownArrow))
{
position.z += speed * Time.deltaTime;
}
transform.position = position;
}
}
The problem is that you are providing a position as an argument to the ScriptableObject.CreateInstance method which is not allowed.
First of all, ScriptableObjects are data containers in Unity and they can't be instantiated into the scene, which means you can't set them up position
Second, you must create your ScriptableObject in the Editor and reference them into the Monobehaviour script attached to some GameObject on the scene
The easiest way to create ScriptableObject is to add CreateAssetMenu as shown below
[CreateAssetMenu(menuName = "Lmovement", fileName = "Lmovement")]
public class Lmovements : ScriptableObject
And after that, you will get the option for creating as you can see in the image below
I am really new to unity and i'm trying to make a PlayerController with different states in different files.
this is the code so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private PlayerState currentState;
void Start()
{
currentState = new PlayerIdle(this);
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
currentState.OnStateUpdate();
}
public void ChangeState(PlayerState newState)
{
currentState.OnStateExit();
currentState = newState;
newState.OnStateEnter();
}
}
how do i fix this?
edit: here is the PlayerIdle code which is supposed to give me the error.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerIdle : PlayerState
{
public CharacterController controller;
public Transform cam;
public GameObject player = GameObject.Find("Player");
public float speed = 12f;
public float gravity = -9.81f;
public float jumpHeight = 3;
public float rotationSpeed;
float x;
float z;
public Transform groundCheck = GameObject.Find("groundCheck").transform;
public float groundDistance = 0.4f;
public LayerMask groundMask;
[SerializeField] Vector3 velocity;
public bool isGrounded;
public float turnSmoothTime = 1f;
float turnSmoothVelocity;
public PlayerIdle(PlayerController playerController) : base(playerController)
{
this.playerController = playerController;
}
public override void OnStateEnter()
{
}
public override void OnStateExit()
{
}
public override void OnStateUpdate()
{
x = Input.GetAxisRaw("Horizontal");
z = Input.GetAxis("Vertical");
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
velocity = player.transform.TransformDirection(Vector3.forward) * speed * z + new Vector3(0f, velocity.y, 0f); ;
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
}
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
velocity.y += gravity * Time.deltaTime;
player.transform.Rotate(new Vector3(0f, x * rotationSpeed, 0f));
controller.Move(velocity * Time.deltaTime);
}
}
any help would be much appreciated :)
also, i found out this is called a statemachine if that helps.
The error says that something in that line is null.
The only thing that can be null is the CurrentState variable.
Probably when you assign it the value of new PlayerIdle (this) in the Start () method, that value is null.
If you can figure out why it's null, you can fix it, but if you're still having trouble you can include the PlayerIdle () code.
A suggestion may be to insert a print (currentState) at the end of Start () to understand if it is actually null.
In addition, also insert a print (new PlayerIdel (this)) in the Update () method to understand if even during the update it continues to be null.
it seems that the update method was being called before the start method (which i still don't understand), so the solution was just to add an if statement before currentState.OnStateUpdate(); saying "if (currentState != null)"
Just picked up Unity about a week ago, I have really been struggling to fix this problem and referencing overall, I'm well aware that I need to read and watch more tutorials, I just want to get this fixed so I can continue working on my game.
An object reference is required for the non-static field, method, or property PlayerMovement.activeMoveSpeed
The first problem was referencing the other Game Object and script, I not sure if its completely fixed now but
at least that not the error that its giving me anymore, I've tried doing what this link says
https://answers.unity.com/questions/1119537/help-how-do-i-referenceaccess-another-script-in-un.html
but as you might see it hasn't worked out, every single time I get the compile errors fixed the script doesn't work because the object reference is not set to an instance of an object, any help would be extremely appreciated (the script I'm trying to reference will be at the end)
Thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShieldAttack : MonoBehaviour
{
public GameObject shield;
private Vector3 mousePos;
private Camera mainCam;
public bool isDashing;
private Rigidbody2D rb;
GameObject Player;
PlayerMovement playerMovement;
Shooting shooting;
// Start is called before the first frame update
void Start()
{
GameObject.FindGameObjectWithTag("EnemyMelee");
GameObject.FindGameObjectWithTag("Enemy2");
mainCam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
mousePos = mainCam.ScreenToWorldPoint(Input.mousePosition);
Vector3 rotation = mousePos - transform.position;
float rotZ = Mathf.Atan2(rotation.y, rotation.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, 0, rotZ);
if (Input.GetKeyDown(KeyCode.Space) && playerMovement.dashCoolCounter <= 0 && playerMovement.dashCounter <= 0)
{
isDashing = true;
Instantiate(shield, shooting.bulletTransform.position, Quaternion.identity);
if (PlayerMovement.activeMoveSpeed == 5)
{
DestroyShield();
isDashing = false;
}
}
}
void DestroyShield()
{
Destroy(gameObject);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rb2d;
private Vector2 moveInput;
public float activeMoveSpeed;
public float dashSpeed;
public float dashLength = 0.5f, dashCooldown = 1f;
public float dashCounter;
public float dashCoolCounter;
[SerializeField] private TrailRenderer tr;
//Start is called before the first frame update
void Start()
{
activeMoveSpeed = moveSpeed;
}
//Update is called once per frame
void Update()
{
if(dashCounter > 0)
{
tr.emitting = true;
}
if(dashCounter < 0)
{
tr.emitting = false;
}
moveInput.x = Input.GetAxisRaw("Horizontal");
moveInput.y = Input.GetAxisRaw("Vertical");
moveInput.Normalize();
rb2d.velocity = moveInput * activeMoveSpeed;
if (Input.GetKeyDown(KeyCode.Space))
{
if (dashCoolCounter <=0 && dashCounter <=0)
{
activeMoveSpeed = dashSpeed;
dashCounter = dashLength;
}
}
if (dashCounter > 0)
{
dashCounter -= Time.deltaTime;
if (dashCounter <= 0)
{
activeMoveSpeed = moveSpeed;
dashCoolCounter = dashCooldown;
}
}
if (dashCoolCounter > 0)
{
dashCoolCounter -= Time.deltaTime;
}
}
}
You are using class name PlayerMovement.activeMoveSpeed instead of object name playerMovement.activeMoveSpeed in this part of code:
if (PlayerMovement.activeMoveSpeed == 5)
{
DestroyShield();
isDashing = false;
}
Also I cannot see playerMovement variable initialization in the ShieldAttack script. You need to mark it with the [SerializeField] attribute or make it public to be able to assign it in the inspector. Or initialize it in your Start() method along with the other fields.
When you create a variable, you do <type> <name>, where <type> is the kind of thing you want to create and <name> is how you want to reference the instance you created.
We as programmers are generally lazy, so if we wanted to create a pineapple we would create an instance of the Pineapple class. What do we call it? Typically just pineapple, and then you wind up with code like
Pineapple pineapple;
The first term means you're wanting to create a Pineapple, and the second term means you're going to refer to that instance as pineapple. Note the capitalization differences there.
The issue with your code is that you've created an instance of PlayerMovement:
PlayerMovement playerMovement;
but when you're trying to use the instance in your code, you are using the class name PlayerMovement and not the instance name playerMovement. Again, note the capitalization difference.
The particular line that you've got:
if (PlayerMovement.activeMoveSpeed == 5)
should instead be:
if (playerMovement.activeMoveSpeed == 5)
to refer to the instance and not the class.
It is possible to have things that are common to all instances of a class. Those are static items and you would access them by referencing the class name instead of the instance name.
The error message you got:
An object reference is required for the non-static field, method, or property PlayerMovement.activeMoveSpeed
was telling you that you were trying to access a part of the class, but it wasn't static, so you needed to reference the object (instance).
This question already has answers here:
Unity: Null while making new class instance
(2 answers)
Closed 5 years ago.
The first script is attached to a empty GameObject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpinableObject
{
public Transform t;
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
}
public class SpinObject : MonoBehaviour
{
public SpinableObject[] objectsToRotate;
private Rotate _rotate;
private int index = 0;
// Use this for initialization
void Start()
{
_rotate = new Rotate>();
}
// Update is called once per frame
void Update()
{
var _objecttorotate = objectsToRotate[index];
_rotate.rotationSpeed = _objecttorotate.rotationSpeed;
_rotate.minSpeed = _objecttorotate.minSpeed;
_rotate.maxSpeed = _objecttorotate.maxSpeed;
_rotate.speedRate = _objecttorotate.speedRate;
_rotate.slowDown = _objecttorotate.slowDown;
}
}
The second script is attached to the GameObject/s i want to feed with information. So this script is attached to each GameObject separate.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotate : MonoBehaviour
{
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
RotateObject();
}
public void RotateObject()
{
if (rotationSpeed > maxSpeed)
slowDown = true;
else if (rotationSpeed < minSpeed)
slowDown = false;
rotationSpeed = (slowDown) ? rotationSpeed - 0.1f : rotationSpeed + 0.1f;
transform.Rotate(Vector3.forward, Time.deltaTime * rotationSpeed);
}
}
Not sure if this is a good way to what i want to do ?
Second problem is that the variable _rotate in the first script is all the time null:
I'm doing:
_rotate = new Rotate>();
But still here it's null:
_rotate.rotationSpeed = _objecttorotate.rotationSpeed;
I don't think you understand how Unity works.
First, _rotate = new Rotate>(); is not valid C# and will throw an error.
Second, in your case Rotate is a MonoBehaviour which is not attached to a GameObject. I think that whatever you tried to accomplish is maybe a step to far. You can' synchronize the Update-call of a deattached Component (of which I don't even know if it gets its Update-method called) with another object at all. In short: Your code seems nonsense to me.
I'd suggest, you move your RotateObject method into the SpinableObject and call it from SpinObject, instead of shoving stuff into _rotate. This should work.
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpinableObject
{
public Transform t;
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
public void RotateObject()
{
if (rotationSpeed > maxSpeed)
slowDown = true;
else if (rotationSpeed < minSpeed)
slowDown = false;
rotationSpeed = (slowDown) ? rotationSpeed - 0.1f : rotationSpeed + 0.1f;
t.Rotate(Vector3.forward, Time.deltaTime * rotationSpeed);
}
}
public class SpinObject : MonoBehaviour
{
[SerializeField]
private SpinableObject[] objectsToRotate;
// Update is called once per frame
void Update()
{
foreach(var spinner in objectsToRotate)
spinner.RotateObject();
}
}