AI, try to use a Method from other Script

Hello Guys

im trying actually to create a AI system based on the Knowledge of another AI Script which using NavMesh. In This System i work with States. My main Problem is that i not sure if i can use NavMesh for my Game because its in the Space and there are Planets Asteroids etc. as Objects but no Ground. I remember that i read about that this not working and everything i tried the Objects only moving on one Height and not go Up or Down. So i try to go a other way to create my AI.

Actually my Ai has 3 Scripts about the Interfaces and 1 Action Script. As example i need the Rotation Action of the NPC in many Scripts so my idea was that i write the Rotate Script in own .cs and then access it from my State Scripts. But if i try to Access the Rotate Script he tells me:

Im not sure if i can make this how i want, perhaps someone can tell me something about why its not working or if theres a different way to handle this.

NPC_State_Interface:
Here is my Interface which Update the State and Contains all possible States (actually only Patrol)

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

namespace enemy
{
public interface NPC_State_Interface

{
        void UpdateState();
        void ToPatrolState();
}
}

NPC_State_Machine, this Script is attached to the NPC from here i want to controll every State every Move every Data from the NPC (later also Health and Shield as example) We initialize every State set the Variables, check the actual State and initialize the Start State which is the Patrol State for now.

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

namespace enemy
{

    public class NPC_State_Machine : MonoBehaviour
    {
        //Check State
        private float checkRate = 0.1f;
        private float nextCheck;

        //NPC Controlloptions
        public float sightRange = 40f;
        public float moveSpeed = 50f;
        public float RayCastOffset = 5f;
        public float speedRotation = 2f;

        //Waypoint
        public GameObject[] waypoints;
       

        //NPC Options
        public MeshRenderer meshRendererFlag;


        //NPC States
        public NPC_State_Interface currentState;       
        public NPC_State_Patrol patrolState;

        void Awake()
        {
           
            SetupUpStateReferences(); //Setup the State References
            Debug.Log("Awake References");
        }

        void Start()
        {
            SetInitialReferences();
        }

        void Update()
        {
            CarryOutUpdateState();
        }

        void SetupUpStateReferences() //Setup the State References
        {
            //Here we need a Reference to every State we wanna use
            patrolState = new NPC_State_Patrol(this);
            Debug.Log("Setup References");
        }

            void SetInitialReferences()
        {
            //The First State every Enemy get actually it is the Patrol State
            ActivatePatrolState();
            Debug.Log("Initial State Reference");
        }

        void CarryOutUpdateState()
        {
            if (Time.time > nextCheck)
            {
                nextCheck = Time.time + checkRate;
                currentState.UpdateState();
                Debug.Log("Update State");
            }
        }

        void ActivatePatrolState() //To Activate the  Patrol State at Beginning
        {
            currentState = patrolState;
            Debug.Log("Activate Patrol State");
        }
    }
}

NPC_State_Patrol, in this Script i tell what to do in the Patrol State, i comment out the Code of the Rotation because i want that he use the Rotation from another Script NPC_Rotate

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

namespace enemy
{
    public class NPC_State_Patrol : NPC_State_Interface
    {
        private readonly NPC_State_Machine npc;       
        private int nextWayPoint = 0;

        public NPC_Rotate rotate;


        public NPC_State_Patrol(NPC_State_Machine npcStateMachine)
        {
            npc = npcStateMachine;
        }

        public void UpdateState()
        {
            Patrol();
            Debug.Log("Patrol");
        }
        public void ToPatrolState() { }

        //Explanation about
        //Here we can write down explicite what the NPC actually have
        //to do in the Patrol State Simple for every NPC he have to Look
        //somewhere and have to Check if theres a Enemy to go in other State
        //i also want to Setup a new Script for an Action and call it. From here

        void Patrol()
        {
           
            Debug.Log("Patrol on Waypoint");
            npc.meshRendererFlag.material.color = Color.blue;

            //here i try to Access the NPC_Rotate Script but he give me the NullReferenceExceptionError
            rotate.RotateTo(npc.waypoints[nextWayPoint].transform.position);
           
            MoveForwards();


            if (HaveIReachedDestination())
            {
                nextWayPoint = (nextWayPoint + 1) % npc.waypoints.Length;
            }

        }

        bool HaveIReachedDestination()
        {
            Vector3 delta = npc.waypoints[nextWayPoint].transform.position - npc.transform.position;

            if (delta.magnitude < npc.RayCastOffset)
            {         
                return true;
                Debug.Log("Reached Destination");
            }
            Debug.Log("Actual Distance:" + delta);
            return false;
        }
        
//If i access the Rotation in this Script its no problem and he rotate to the target position but this is not what i want xD

        /*public void RotateTo(Vector3 targetPosition)
        {
            Quaternion destRotation;
            Vector3 relativePos;
            Debug.Log("Rotate");
            relativePos = targetPosition - npc.transform.position;

            destRotation = Quaternion.LookRotation(relativePos);
            npc.transform.rotation = Quaternion.Slerp(npc.transform.rotation, destRotation, npc.speedRotation * Time.deltaTime);
        }*/

        public void MoveForwards()
        {
//Simple Move Forward and comment out the RotateTo function in this method
            npc.transform.position += npc.transform.forward * Time.deltaTime * npc.moveSpeed;
            //RotateTo(npc.waypoints[nextWayPoint].transform.position);
        }

    }
}

NPC_Rotate just a simple rotation for the NPC which i want call from different States

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

namespace enemy
{
    public class NPC_Rotate : MonoBehaviour
    {
        public NPC_State_Machine npc;

        public void RotateTo(Vector3 targetPosition)
        {
            Quaternion destRotation;
            Vector3 relativePos;
           
            relativePos = targetPosition - npc.transform.position;

            destRotation = Quaternion.LookRotation(relativePos);
            npc.transform.rotation = Quaternion.Slerp(npc.transform.rotation, destRotation, npc.speedRotation * Time.deltaTime);

            Debug.Log("Rotate");
        }
    }
}

Uh long now, i hope u guys can understand what i want and help me out a little bit with ideas ore solving my problem. Thanks everyone and feel free to ask for more Information if need.

That was a long post, but your issue about the Null reference means that you haven’t assigned that variable properly (whether through the inspector or some other means). Just drag the game object with the NPC_Rotate script to that spot in the inspector and try again.

If you have more questions, it might be helpful to post just what’s relevant to the (any remaining) question. :slight_smile:

Hehe i think all relevant thats my problem, im still a beginner hehe xD

I know what u wanna try to tell me but even i attach the Rotate Script to the NPC and Setup

public NPC_State_Machine npc;

he still tell me he have NullReferenceException.

But i not want to attach the Rotate script to the NPC, i want him to use it without, so that i just call the Method inside the Script because he should know already that its his own transform.position because NPC_State_Machine attached to the NPC and this Script should change the npc.transform and get called by the Patrol Script in the Rotate Script

Example
In Patrol he rotate to Target Waypoint (NPC_State_Patrol)
In Attack he rotate to Target Attack (NPC_State_Attack) (not integrated yet)

so i need the Rotation in both States each have his own Script which controlled by NPC_State_Machine

i think my problem come with this:

public void RotateTo(Vector3 targetPosition)

I give from NPC_State_Patrol the

rotate.RotateTo(npc.waypoints[nextWayPoint].transform.position);

the Waypoints all attached to NPC_State_Machine and he should send the next waypoint position he get from NPC_State_Machine to NPC_Rotate to rotate to the target.

But after i write this all i think about the Option to attach the Script to the NPC too. because i not have to change something in this Script its just attached. But then i have the Problem i tell at top. Even i Attach he still tell me NullReferenceException. But i look forward and try the new Ideas i get now from ur and my Post. (sometimes also just very useful if u write down ur problem) and someone kick ur Mind a bit xD

I couldn’t understand exactly what you were saying, but if you want to use the variable (that refers to something else), you have to link it in so it’s known/set … and can be used.

If it’s still giving you the error about being null, and you’re sure it’s that line & not the ‘rotate’ variable, then check to be sure that your ‘npc.waypoints’ are setup correctly. :slight_smile: Gotta be one or the other, in that line, I think.