Unity 2D - доступ к переменным GetComponent <T>, отправляемым как параметр - PullRequest
0 голосов
/ 13 января 2019

У меня есть этот скрипт для сохранения моего персонажа. У меня много неигровых персонажей, и у каждого есть свой сценарий. Я хочу использовать метод SaveCharacter для сохранения каждого NPC. Как я могу отправить g.GetComponent<Warrior_Movement>() в качестве параметра и получить доступ к его переменным? Когда я использую <T>, я не могу получить переменные скрипта gameobject. Спасибо

void SaveCharacter(Character character, string gameObjectName)
{
    GameObject g = GameObject.Find(gameObjectName);

    character.position = new float[] { g.transform.position.x, g.transform.position.y, g.transform.position.z };
    character.selectedScheme = g.GetComponent<Warrior_Movement>().selectedScheme;
    character.currentWaypointIndex = g.GetComponent<Warrior_Movement>().currentWaypointIndex;
    character.nextWaypointIndex = g.GetComponent<Warrior_Movement>().nextWaypointIndex;
    character.loopSide = g.GetComponent<Warrior_Movement>().loopSide;
}

1 Ответ

0 голосов
/ 14 января 2019

Задача

Вы можете НЕ использовать переменную для передачи ее в общую версию GetComponemt, например

public void DoSomething(Type componemtType)
{
    var component = GetComponent<componentType>();
}

, поскольку типы, используемые для реализации обобщений, должны быть постоянной времени компиляции и поэтому не могут быть переменной (или только той, которая является постоянной времени компиляции)!

Вы можете использовать неуниверсальную версию GetComponent, такую ​​как

public void DoSomething(Type componentType)
{
    var component = GetComponent(componentType);
}

но , чем вам нужно было бы проанализировать его, чтобы иметь доступ к любым полям или методам, специфичным для этого компонента:

var parsedComponent = component as componentType;

И снова вы можете НЕ сделать это, поскольку тип, используемый для as, также должен быть постоянной времени компиляции и поэтому не может быть переменной.


Решение 1: Общий базовый класс

В случае, если все ваши разные классы имеют общие поля, которые вы хотите сохранить, все они должны наследоваться от общего базового типа, например,

// By making a class abstract it can not be instanced itself but only be implemented by subclasses
public abstract class BaseMovement : MonoBehaviour
{
    // fields that will be inherited by subclasses
    public int currentWaypointIndex;
    public int nextWaypointIndex;
    //...

    // You could also have some generic methods that are implemented
    // only in the subclasses like e.g. Getters for the values
    // you want to access
    public abstract string SaySomething();
}

А чем наследовать ваши классы от таких как например

public class Warrior_Movement : BaseMovement
{
    // Inherits all fields of BaseMovement

    //... additional type specific stuff

    // If you have abstract methods in the base class
    // every subclass has to implement all of them
    public override string SaySomething()
    {
        return "Harr harr, I'm a warrior!";
    }
}

public class Other_Movement : BaseMovement
{
    // Inherits all fields of BaseMovement

    // Additional type specific stuff

    // If you have abstract methods in the base class
    // every subclass has to implement all of them
    public override string SaySomething ()
    {
        return "Harr harr, I'm ... something else :'D ";
    }
}

Чем вы можете использовать что-то вроде

void SaveCharacter(Character character, BaseMovent bMovement)
{
    character.position = new float[] { bMovement.transform.position.x, bMovement.transform.position.y, bMovement.transform.position.z };
    character.currentWaypointIndex = bMovement.currentWaypointIndex;
    character.nextWaypointIndex = bMovement.nextWaypointIndex;
}

и назовите это как

GameObject g = GameObject.Find(gameObjectName);
var movement = g.GetComponemt<BaseMovement>();

SaveCharacter(someCharacter, movement);

Решение 2. Перегрузки

В качестве альтернативы, если вы используете разные значения для разных компонентов, чем не используете общий базовый класс, а вместо этого создаете перегрузки SaveCharacter, такие как

public void SaveCharacter(Character character, Warrior_Movement wMovement)
{
    // Do stuff with wMovement
    // ...
}

public void SaveCharacter (Character character, Other_Movement oMovement)
{
    // Do stuff with oMovement
    // ...
}

, поэтому, когда вы используете SaveCharacter, типы, которые вы передаете, будут определять, какую реализацию SaveCharacter следует использовать.


К

Когда я использую, я не могу получить переменные скрипта gameobject.

Я не знаю, что именно вы имеете в виду, но вы можете получить доступ к GameObject, к которому прикреплен компонент, используя gameObject например,

bMovement.gameObject.SetActive(true);

Примечание
Если это возможно, вам следует избегать использования Find, так как это довольно интенсивно. Попробуйте получить ссылку как можно скорее, например, либо путем ссылки на него в Инспекторе с использованием поля public GameObject, либо, если оно установлено, сохраните его в переменной типа

var warrior = Instantiate (/*...*/);

и раздайте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...