Unity场景中敌人脚本自动查找Player Transform对象问题——新手开发者求助
Hey there! Let's break down why your current code is throwing an error and fix it properly.
The Root Cause
You can't use GameObject.Find("Player") directly when initializing a class field like public Transform player = GameObject.Find("Player"); in Unity. Here's why:
- When your script's fields are initialized (before
Awake()orStart()runs), Unity hasn't fully loaded the scene or spawned all GameObjects yet. The Player object might not exist in the scene at this point, soFind()returnsnull—which causes errors when you try to accessplayer.positioninUpdate().
The Fix: Move the Lookup to Awake() or Start()
We'll move the Player lookup into the Awake() method (which runs before Start(), ensuring we have the Player reference ready for the first frame of Update()). We'll also add a safety check to catch cases where the Player isn't found, so you get a clear warning instead of a cryptic error.
Here's the revised script:
public class Enemies : MonoBehaviour { // Declare the field without initializing it here private Transform player; private Rigidbody2D rb; private Vector2 movement; public float speed = 5f; public int health; // Awake runs before Start, perfect for initializing references void Awake() { // Find the Player GameObject and get its Transform component GameObject playerObj = GameObject.Find("Player"); if (playerObj != null) { player = playerObj.GetComponent<Transform>(); } else { Debug.LogWarning("Player GameObject not found in the scene! Make sure it's named exactly 'Player'."); } } // Start is called before the first frame update void Start() { rb = this.GetComponent<Rigidbody2D>(); } // Update is called once per frame void Update() { // Add a check to avoid null reference errors if Player isn't found if (player == null) return; Vector2 direction = player.position - transform.position; float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; rb.rotation = angle; direction.Normalize(); movement = direction; } private void FixedUpdate() { // Only move if we have a valid Player reference if (player == null) return; Move(movement); } void Move(Vector2 direction) { rb.MovePosition((Vector2)transform.position + (direction * speed * Time.deltaTime)); } private void OnMouseDown() { health = health - 1; if(health <= 0) { Destroy(gameObject); } } }
Bonus: A More Reliable Alternative (Using Tags)
If you ever rename your Player GameObject, GameObject.Find("Player") will break. A better approach is to use Tags:
- Select your Player GameObject in the Hierarchy.
- In the Inspector, set its Tag to "Player" (create the tag if it doesn't exist).
- Replace the lookup line in
Awake()with:
GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
This way, even if you rename the Player, as long as the Tag stays "Player", the lookup will work.
Why This Works
- By moving the lookup to
Awake(), we wait until Unity has loaded all scene objects before trying to find the Player. - The null checks prevent your script from trying to access a non-existent Player reference, which avoids runtime errors.
内容的提问来源于stack exchange,提问作者Vadim

