Home > OS >  How do you use a variable declared inside a function in another function? (C#) UnassignedReferenceEx
How do you use a variable declared inside a function in another function? (C#) UnassignedReferenceEx

Time:05-20

Represents wat i want

So i'm playing around in Unity MLAgents, and wanted to add the position off objects that a Raycast hits to the agent's observations. This has really been an adventure for me as i don't know anything about Unity or C#, and i know this sounds easy and it probably is:

I'm getting error CS0103: The name 'inRay' does not exist in the current context.

And ok, i tried to declare in the global scope and the error is gone but then when running the code it gives me:

UnassignedReferenceException: The variable inRay has not ben assigned.

This is in one Script and i can't think of anything else i could do to solve the reference issue.

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;
        }
    }
    
}

CodePudding user response:

var inRay = rayHit.transform;

You're creating a new local variable instead of assigning your member variable here. Remove the var.

You should still check that your member variable is assigned before using it, maybe if (inRayr != null) could help.

CodePudding user response:

The field you declared within the Agent should be instantiated within the constructor. So just give it an default value or make it null. The Compiler optimises this value and throws an exception because it thinks the field was never declared and thus is never used. As you see all your other fields have been set with an default value, and those don´t throw an error.

  • Related