如何在另一个函数中使用函数内部声明的变量? (C#) UnassignedReferenceException: 变量 inRay 没有被赋值

How do you use a variable declared inside a function in another function? (C#) UnassignedReferenceException: The variable inRay has not ben assigned

所以我在 Unity MLAgents 中玩耍,想将 Raycast 击中的对象的位置添加到代理的观察中。 这对我来说真的是一次冒险,因为我对 Unity 或 C# 一无所知,而且我知道这听起来很简单,可能是:

我收到错误 CS0103:名称 'inRay' 在当前上下文中不存在。

好吧,我尝试在全局范围内声明并且错误消失了,但是当 运行 它给我的代码时:

UnassignedReferenceException: 变量 inRay 没有被赋值。

这是一个脚本,我想不出我还能做些什么来解决参考问题。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;


public class AgentBasicController : Agent
{
    private Rigidbody rigidA;
    private float yThrust = 0.125f;
    private float moveSpeed = 5f;
    private float timer = 60f;
    public Transform inRay;

    
    public override void Initialize()
    {
        rigidA = GetComponent<Rigidbody>();
    }

    public override void OnEpisodeBegin()
    {
        timer = 60f;

        if (timer <= 0f)
        {
            SetReward(-1F);
            timer = 60f;
        }
    }

    public override void CollectObservations(VectorSensor sens)
    {
        sens.AddObservation(transform.localPosition);
        sens.AddObservation(inRay.localPosition);
    }
    
    public override void OnActionReceived(ActionBuffers acts)
    {
        int moveX = acts.DiscreteActions[0];
        int moveZ = acts.DiscreteActions[1];
        
        if (Mathf.FloorToInt(acts.DiscreteActions[2]) == 1)
        {
            Jump();
        }

        if (Mathf.FloorToInt(acts.DiscreteActions[3]) == 1)
        {
            SensRay();
        }

        Vector3 addForce = new Vector3(0, 0, 0);

        switch (moveX)
        {
            case 0: addForce.x = 0f; break;
            case 1: addForce.x = -1f; break;
            case 2: addForce.x = +1f; break;
        }

        switch (moveZ)
        {
            case 0: addForce.z = 0f; break;
            case 1: addForce.z = -1f; break;
            case 2: addForce.z = +1f; break;
        }

        rigidA.velocity = addForce * moveSpeed + new Vector3(0, rigidA.velocity.y, 0);
    }

    public override void Heuristic(in ActionBuffers actsOut)
    {
        ActionSegment<int> discreteActs = actsOut.DiscreteActions;

        switch (Mathf.RoundToInt(Input.GetAxisRaw("Horizontal")))
        {
            case -1: discreteActs[0] = 1; break;
            case 0: discreteActs[0] = 0; break;
            case +1: discreteActs[0] = 2; break;
        }

        switch (Mathf.RoundToInt(Input.GetAxisRaw("Vertical")))
        {
            case -1: discreteActs[1] = 1; break;
            case 0: discreteActs[1] = 0; break;
            case +1: discreteActs[1] = 2; break;
        }

        discreteActs[2] = 0;

        if (Input.GetKey(KeyCode.Space))
        {
            discreteActs[2] = 1;
        }

        discreteActs[3] = 0;

        if(Input.GetKey(KeyCode.R))
        {
            discreteActs[3] = 1;
        }
    }

    private void Jump()
    {
        if (transform.localPosition.y <= 1f)
        {
            rigidA.AddForce(new Vector3(0, yThrust , 0), ForceMode.Impulse);
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Goal"))
        {
            SetReward(+1f);
            EndEpisode();
        }
    
        if (other.CompareTag("Rift"))
        {
            SetReward(-1f);
            EndEpisode();
        }
    }

    public void SensRay()
    {
        RaycastHit rayHit;
        if (Physics.Raycast(transform.localPosition, (transform.TransformDirection(Vector3.forward)), out rayHit) || 
        Physics.Raycast(transform.localPosition, (transform.TransformDirection(Vector3.right)), out rayHit) ||
        Physics.Raycast(transform.localPosition, (transform.TransformDirection(Vector3.left)), out rayHit) ||
        Physics.Raycast(transform.localPosition, (transform.TransformDirection(Vector3.back)), out rayHit))
        {
            var inRay = rayHit.transform;

            if (inRay.CompareTag("Goal"))
            {
                Vector3 target = rayHit.transform.localPosition;
                Vector3 current = transform.localPosition;

                transform.localPosition = Vector3.MoveTowards(current, target, moveSpeed);
            }
        }
        Debug.DrawRay(transform.position, (transform.TransformDirection(Vector3.forward)), Color.yellow);
        Debug.DrawRay(transform.position, (transform.TransformDirection(Vector3.right)), Color.yellow);
        Debug.DrawRay(transform.position, (transform.TransformDirection(Vector3.left)), Color.yellow);
        Debug.DrawRay(transform.position, (transform.TransformDirection(Vector3.back)), Color.yellow);
    }

    private void Update()
    {
        if (timer <= 0f)
        {
            SetReward(-1F);
            timer = 60f;
        }
    }
    
}

var inRay = rayHit.transform;

您正在创建一个新的局部变量,而不是在此处分配您的成员变量。删除 var.

您仍然应该在使用之前检查您的成员变量是否已分配,也许 if (inRayr != null) 可以提供帮助。

您在代理中声明的字段应在构造函数中实例化。所以只要给它一个默认值或者让它为空。 编译器优化此值并抛出异常,因为它认为该字段从未声明过,因此也从未使用过。 如您所见,所有其他字段都已设置为默认值,并且不会引发错误。