简体   繁体   中英

How do I access the custom class by knowing a variable from that class?

I created a custom class:

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

[System.Serializable]
public class Obstacle {
    public GameObject gameObj;
    public Color color;

    public GameObject starExplosion;
    public GameObject regular_Trail;
    [HideInInspector]
    public bool firstCollistion = true;

    public static Vector3 SpawnLocation()
    {
        int positionQuadran = Random.Range(1, 3);
        switch (positionQuadran)
        {
            //spawn above the player
            case 1:
                 return new Vector3(Random.Range(1.5f, -1.5f),
                                                      Random.Range(4f - SpawnStars.closerToPlayer, 4.5f),
                                                      Random.Range(1, -3.2f));
            //spawn benith the player
            case 2:
                return new Vector3(Random.Range(1.5f, -1.5f),
                                                      Random.Range(-0.5f, SpawnStars.closerToPlayer),
                                                      Random.Range(1f, -3.2f));
        }
        return Vector3.zero;
    }
}

Now, as you can see in this class there is a variable public GameObject gameObj; Now in another script I need to acces the instance of the Obstacle class that this gameObj instance is in. And I am trying to do that like this:

private void OnCollisionEnter(Collision collision)
{
    collision.collider. //what do I do next?
}

For a few reasons I don't want to make the Obstacle class inherit from MonoBehaviour . Since I can't access this class from another GameObject that would be in the scene how do I access it by only knowing the gameObj variable?

Update I will add the script that I use to generate the Obstacle Class:

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


public class SpawnStars : MonoBehaviour
{
    [SerializeField]
    private List<Obstacle> obstacles;
    [HideInInspector]
    public List<Obstacle> normalStarsPool = new List<Obstacle>();

    [SerializeField]
    private List<Obstacle> otherObstacles;
    [HideInInspector]
    public List<Obstacle> otherObstaclesPool;

    [SerializeField]
    private int spawnNumber = 2;

    private Obstacle nextObstacleToSpawn;
    [SerializeField]
    public GameObject panel;
    public static bool spawnNow = true;
    public static bool first_find_star = true;

    public static float starSpeed;
    /* this variables will make the stars to spawn closer and closer to the player as 
    the score  is progresing*/
    public static float closerToPlayer;
    private float spawnPositionZ;

    private void Start()
    {
        first_find_star = true;
        spawnNow = true;

        GeneratePrefabs(spawnNumber, obstacles, normalStarsPool);
        StartCoroutine(ShuffleList(normalStarsPool));

        GeneratePrefabs(2, otherObstacles, otherObstaclesPool);
        StartCoroutine(ShuffleList(otherObstaclesPool));
    }
    private void LateUpdate()
    {
        if (spawnNow)
        {
            spawnNow = false;
            if (first_find_star)
            {
                nextObstacleToSpawn = FindStar(normalStarsPool);
                first_find_star = false;
            }
            //spawn the current star
            int randomNumber = Random.Range(0, 100);
            if(randomNumber >= 20){
                nextObstacleToSpawn = FindStar(normalStarsPool);
            }
            else{
                Debug.Log("corrupt star");
                nextObstacleToSpawn = FindStar(otherObstacles);
            }
            SpawnStar(nextObstacleToSpawn);

        }
    }
    void GeneratePrefabs(int how_many, List<Obstacle> prefabList, List<Obstacle> poolList)
    {
        foreach (Obstacle prefab in prefabList)
        {
            for (int i = 0; i <= how_many; i++)
            {
                Obstacle go = new Obstacle
                {
                    gameObj = Instantiate(prefab.gameObj)
                };
                go.regular_Trail = go.gameObj.transform.GetChild(1).gameObject;
                go.starExplosion = go.gameObj.transform.GetChild(0).gameObject;
                go.color = prefab.color;
                go.gameObj.SetActive(false);

                //setap all the colors for the obstacle
                ParticleSystem ps = go.starExplosion.GetComponent<ParticleSystem>();
                ParticleSystem.MainModule psmain = ps.main;
                psmain.startColor = go.color;

                //setup the collor of a partycle system
                ps = go.starExplosion.GetComponent<ParticleSystem>();
                psmain = ps.main;
                psmain.startColor = go.color;

                psmain.startColor = go.color;

                go.gameObj.GetComponent<Renderer>().material.color = go.color;
                poolList.Add(go);
            }
        }
    }
    Obstacle FindStar(List<Obstacle> poolList)
    {
        while (true)
        {
            int randomIndex = Random.Range(0, poolList.Count);
            if (!poolList[randomIndex].gameObj.activeInHierarchy)
            {
                Color color = poolList[randomIndex].color;
                color.a = 0.5f;
                panel.GetComponent<Renderer>().material.color = color;
                return poolList[randomIndex];
            }
            else randomIndex = Random.Range(0, poolList.Count);
        }
    }
        void SpawnStar(Obstacle star)
    {
        star.firstCollistion = false;
        star.starExplosion.SetActive(false);
        star.regular_Trail.SetActive(true);
        star.gameObj.GetComponent<MeshRenderer>().enabled = true;
        ScaleDifficulty();
        star.gameObj.transform.position = Obstacle.SpawnLocation();
        star.gameObj.SetActive(true);
    }

    //Shuffle a list every 4 seconds, don't pus this in an update or something cuz it's a coroutine
    IEnumerator ShuffleList(List<Obstacle> list_to_Shuffle)
    {
        while (true)
        {
            yield return new WaitForSeconds(4f);
            for (int i = 0; i < list_to_Shuffle.Count; i++)
            {
                Obstacle temp = list_to_Shuffle[i];
                int randomIndex = Random.Range(i, list_to_Shuffle.Count);
                list_to_Shuffle[i] = list_to_Shuffle[randomIndex];
                list_to_Shuffle[randomIndex] = temp;
            }
        }
    }
    //this will scale the difficulty as the score get's higher and higher
    public void ScaleDifficulty()
    {
        if (Menu.score < 60)
        {
            //the speed of the star as the score goes up
            starSpeed = ((float)Menu.score / 30) + 1f;
            //how close relative to the player will the stars spawn in the x and y axis?
            closerToPlayer += Menu.score / 60;
           // Debug.Log(starSpeed);
        }
    }
}

As you can see i generated the Obstacle objects in this method:

void GeneratePrefabs(int how_many, List<Obstacle> prefabList, List<Obstacle> poolList)
{
    foreach (Obstacle prefab in prefabList)
    {
        for (int i = 0; i <= how_many; i++)
        {
            Obstacle go = new Obstacle
            {
                gameObj = Instantiate(prefab.gameObj)
            };
            go.regular_Trail = go.gameObj.transform.GetChild(1).gameObject;
            go.starExplosion = go.gameObj.transform.GetChild(0).gameObject;
            go.color = prefab.color;
            go.gameObj.SetActive(false);

            //setap all the colors for the obstacle
            ParticleSystem ps = go.starExplosion.GetComponent<ParticleSystem>();
            ParticleSystem.MainModule psmain = ps.main;
            psmain.startColor = go.color;

            //setup the collor of a partycle system
            ps = go.starExplosion.GetComponent<ParticleSystem>();
            psmain = ps.main;
            psmain.startColor = go.color;

            psmain.startColor = go.color;

            go.gameObj.GetComponent<Renderer>().material.color = go.color;
            poolList.Add(go);
        }
    }
}

Now in another script I need to acces the instance of the Obstacle class that this gameObj instance is in.

Given an instance of an Obstacle class, how can you even know that it is referenced by an instance of GameObject at all? Or how can you know that it's referenced by only one GameObject?

Unless there's a two-way reference - the GameObject has a reference to the Obstacle and the Obstacle also has a reference back to the GameObject - there's no way to determine what references an instance of Obstacle .

In short, you can't. Not the way you've got things set up. If you need to access that object globally, you'll need to keep track of it globally. Unity provides a way to do that (essentially the Service Locator pattern ), but you've said you don't want to use it. So you're going to have to build your own.

Assuming you've got a collection of your Obstacle objects, eg IList<Obstacle> obstacles you could get it by obstacles.Where(o => o.gameObj == myLocalGameObjReference) . A better solution, assuming you have this script attached 1:1 for each Obstacle would be to simple inject the Obstacle into the script. Look at a dependency injection (DI) framework like Zenject to assist with configuring and managing your dependencies. Another alternative is the singleton pattern . Personally, I'd opt for DI over singleton. The singleton seems easier at first, but you'll quickly run into trouble with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM