尝试从另一个类/对象引用一个公共属性,但它始终为空。

huangapple go评论92阅读模式
英文:

Trying to reference a public property from another class/object and it's always null

问题

我有一个附加到名为GameManager的空对象的C#脚本。该脚本名为GameManager.cs。以下是前几行:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {
    public GameObject tilePrefab;
    public GameObject startTile;
    public GameObject lastTile;

我有另一个附加到摄像机的脚本,名为CameraManager.cs。我试图从GameManager引用lastTile,但它始终为null。以下是CameraManager.cs的完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraManager : MonoBehaviour
{
    private Vector3 currPos;
    private Vector3 newPos;
    public float CamMoveSpeed = 5f;
    GameManager gameManager;

    private void Awake() {
        gameManager = gameObject.AddComponent<GameManager>();
    }
    private void Start() {
    }

    private void Update() {
        if (gameManager.lastTile != null) {
            currPos = gameObject.transform.position;
            Vector3 tilePos = gameManager.lastTile.transform.position;
            newPos = new Vector3(currPos.x + tilePos.x, currPos.y + tilePos.y, currPos.z + tilePos.z);
            this.transform.position = Vector3.Lerp(currPos, newPos, CamMoveSpeed * Time.deltaTime);
            Debug.Log("Moving Camera...");
        } else {
            Debug.LogWarning("gameManager.lastTile is NULL");
        }
    }
}

这个最新的版本基于这个Stack Overflow问题。之前的版本基于这个Stack Overflow问题

引用另一个脚本/类的值的正确方法是什么?

英文:

I have a C# script attached to an empty object called GameManager. The script is GameManager.cs. Here are the first few lines:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {
	public GameObject tilePrefab;
	public GameObject startTile;
	public GameObject lastTile;

I have another script attached to a camera called CameraManager.cs. I'm attempting to reference lastTile from GameManager but it's always null. Here is the full code for CameraManager.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraManager : MonoBehaviour
{
	// Start is called before the first frame update
	private Vector3 currPos;
	private Vector3 newPos;
	public float CamMoveSpeed = 5f;
	GameManager gameManager;

	private void Awake() {
		gameManager = gameObject.AddComponent&lt;GameManager&gt;();
	}
	private void Start() {
	}

	private void Update() {
		if (gameManager.lastTile != null) {
			currPos = gameObject.transform.position;
			Vector3 tilePos = gameManager.lastTile.transform.position;
			newPos = new Vector3(currPos.x + tilePos.x, currPos.y + tilePos.y, currPos.z + tilePos.z);
			this.transform.position = Vector3.Lerp(currPos, newPos, CamMoveSpeed * Time.deltaTime);
			Debug.Log(&quot;Moving Camera...&quot;);
		} else {
			Debug.LogWarning(&quot;gameManager.lastTile is NULL&quot;);
		}
	}
}

This latest iteration is based on this SO question. The previous iteration was based on this SO question.

What is the proper way to reference a value from another script/class?

答案1

得分: 1

我只需将属性设为public,然后在检视器中将其分配给GameManager对象的相应字段。我能够在awake方法中移除所有内容。

英文:

All I had to do was make the property public and then assign it in the inspector by dragging the GameManager object to the corresponding field. I was able to remove everything in the awake routine.

尝试从另一个类/对象引用一个公共属性,但它始终为空。

答案2

得分: 0

在你的相机类的awake方法中,你使用AddComponent方法为gameManager分配了一个新实例的GameManager脚本,这个新实例被创建在与相机管理类相同的对象上。这意味着相机管理类引用的GameManager类实际上不是在GameManager游戏物体上的那个。

通常,人们在处理GameManager类时会使用单例结构。

基本上,你可以在GameManager类中创建一个静态字段,类型为GameManager,并在GameManager类的Awake方法中将其分配为自身的实例。类似这样:

public class GameManager : MonoBehaviour {
    public GameObject tilePrefab = new GameObject("Name");
    public GameObject startTile = new GameObject("Name");
    public GameObject lastTile = new GameObject("Name");

    public static GameManager Instance;

    private void Awake(){
        Instance = this;
    }
}

然后,你可以在任何其他类中使用你的游戏管理器,使用这一行代码:GameManager.Instance.lastTile

英文:

In the awake method of your camera class you assign gameManager with AddComponent, that will create a new instance of the GameManager script on the same object that your camera manager class is on, meaning that the reference that your camera manager class has to the GameManager class is not the one that’s on your GameManager gameObject.

What people do usually with GameManager classes is to use a Signlton structure

Basically you can have a static field of type GameManager in your GameManager class and assign it to its own instance on the Awake method of your GameManager class. Something like this

public class GameManager : MonoBehaviour {
    public GameObject tilePrefab = new GameObject(&quot;Name&quot;);
    public GameObject startTile = new GameObject(&quot;Name&quot;);
    public GameObject lastTile = new GameObject(&quot;Name&quot;);

    public static GameManager Instance;

    private void Awake(){
        Instance = this;
    }
}

And then you can use your game manager in any other class with this line GameManager.Instance.lastTitle

答案3

得分: -3

public class GameManager : MonoBehaviour {
    public GameObject tilePrefab;
    public GameObject startTile;
    public GameObject lastTile;
}

看起来你从未将这些变量分配给任何内容,因此它们将始终为null。

要使它们不为null,你需要将它们分配给某些内容,例如:

public class GameManager : MonoBehaviour {
    public GameObject tilePrefab = new GameObject("Name");
    public GameObject startTile = new GameObject("Name");
    public GameObject lastTile = new GameObject("Name");
}

或者你可以通过以下方式动态设置它们:

private void Update() {
    gameManager.lastTile = new GameObject("Name");
}
英文:
public class GameManager : MonoBehaviour {
    public GameObject tilePrefab;
    public GameObject startTile;
    public GameObject lastTile;
}

It doesnt look like your ever assigning these variables to anything, therefore they will always be null.

For them not to be null you need to assign them to something e.g.

public class GameManager : MonoBehaviour {
    public GameObject tilePrefab = new GameObject(&quot;Name&quot;);
    public GameObject startTile = new GameObject(&quot;Name&quot;);
    public GameObject lastTile = new GameObject(&quot;Name&quot;);
}

Or you can set them dynamically by doing

private void Update() {
    gameManager.lastTile = new GameObject(&quot;Name&quot;);
}

huangapple
  • 本文由 发表于 2023年2月19日 06:46:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496847.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定