Unity Dynami c GetComponent erronr - PullRequest
       6

Unity Dynami c GetComponent erronr

0 голосов
/ 25 апреля 2020

Я занимаюсь защитой башни. Есть разные узлы, на которых стоит турель. Вы получаете этот GameObject с функцией Node.activeNode.GetTurret (). У каждого типа башни есть свой сценарий, поэтому у него свой класс. Я хочу изменить текст на переменную из скрипта текущей башни, но я не знаю, какой скрипт у текущей башни, поэтому мой скрипт выглядит так:

       GameObject _turret = Node.activeNode.GetTurret();

        if (_turret.TryGetComponent(out CrossbowScript crossbowScript))
        {
            statsText[0].SetText(crossbowScript.damage.ToString());
            statsText[1].SetText(crossbowScript.fireRate.ToString());
            statsText[2].SetText(crossbowScript.range.ToString());
            statsText[3].SetText(crossbowScript.bulletPenetration.ToString());
            return;
        }
        else if(_turret.TryGetComponent(out BlitzScript blitzScript))
        {
            statsText[0].SetText(blitzScript.damage.ToString());
            statsText[1].SetText(blitzScript.fireRate.ToString());
            statsText[2].SetText(blitzScript.range.ToString());
            statsText[3].SetText(blitzScript.bulletPenetration.ToString());
            return;
        }
        else if (_turret.TryGetComponent(out CannonScript cannonScript))
        {
            statsText[0].SetText(cannonScript.damage.ToString());
            statsText[1].SetText(cannonScript.fireRate.ToString());
            statsText[2].SetText(cannonScript.range.ToString());
            statsText[3].SetText(cannonScript.bulletPenetration.ToString());
            return;
        }

Есть ли способ, чтобы Я могу использовать GetComponent в целом, так что мне не всегда приходится запрашивать для каждой башни, включен ли скрипт для него, а если нет, то смотреть дальше. Я подумал, что вы могли бы создать скрипт, который есть на каждой башне и всегда одинаковый, а затем возвращает тип скрипта башни, но я не знаю, как сделать функцию, которая возвращает в зависимости от другого типа. (Это просто идея, если у вас есть лучшая, пожалуйста, напишите это) Заранее спасибо за ваши отличные ответы

Вот полный CrossbowScript:

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

public class CrossbowScript : MonoBehaviour
{
    private Transform target;

    [Header("Attributes")]
    public float damage = 10f;
    public float fireRate = 1f;
    public float range = 15f;
    public float bulletPenetration = 5f;
    private float fireCountdown = 0f;
    public float turnSpeed = 10f;

    [Header("Upgrading")]
    public float upgradeDamage = 5f;
    public float upgradeFireRate = 0.2f;
    public float upgradeRange = 2f;
    public float upgradeBulletPenetration = 1f;

    [Header("Unity Setup Fields")]
    public string enemyTag = "Enemy";

    public Transform partToRotate;

    public GameObject bulletPrefab;
    public Transform firePoint;
    public Animator anim;



    void Start()
    {
        //UpdateTarget wird 2 mal pro sec ausgeführt
        InvokeRepeating ("UpdateTarget", 0f, 0.5f);
    }


    void UpdateTarget () {
        //Gegner Finden und den nähesten herausfinden
        GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        float shortestDistance = Mathf.Infinity;
        GameObject nearestEnemy = null;

        foreach (GameObject enemy in enemies) {
            float distanceToEnemy = Vector3.Distance (transform.position, enemy.transform.position);
            if (distanceToEnemy < shortestDistance) {
                shortestDistance = distanceToEnemy;
                nearestEnemy = enemy;
            }
        }

        if (nearestEnemy != null && shortestDistance <= range) {
            target = nearestEnemy.transform;
        }else{
            target = null;
        }
    }

    void Update()
    {
        if(anim.GetBool("IsShooting")) {
            anim.SetBool("IsShooting", false);
        }
        if (target == null) {
            return;
        }

        //Auf den Target schauen
        Vector3 dir = target.position - transform.position;
        Quaternion lookRotation = Quaternion.LookRotation(dir);
        Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
        partToRotate.rotation = Quaternion.Euler (0f, rotation.y, 0f);

        if (fireCountdown <= 0f) {
            Shoot();
            fireCountdown = 1f / fireRate;
        }

        fireCountdown -= Time.deltaTime;
    }

    void Shoot () {
        GameObject bulletGO = (GameObject)Instantiate (bulletPrefab, firePoint.position, firePoint.rotation);
        //Neue Variable Bullet, Name der Variable arrow, arrowGo ist das Gameobject dass instanziert wurde, GetComponent<Bullet> man bekommt das Script Bullet
        Bullet bullet = bulletGO.GetComponent<Bullet>();
        anim.SetBool("IsShooting", true);
        if(bullet != null) {
            bullet.Seek(target, damage, bulletPenetration);
        }
    }

    void OnDrawGizmosSelected () {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, range);
    }

    public void Upgrade(int attribute)
    {
        switch (attribute)
        {
            case 0:
                damage += upgradeDamage;
                break;
            case 1:
                fireRate += upgradeFireRate;
                break;
            case 2:
                range += upgradeRange;
                break;
            case 3:
                bulletPenetration += upgradeBulletPenetration;
                break;
        }
    }
}

А вот полный CannonScript:

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

public class CannonScript : MonoBehaviour
{
    private GameObject target;

    [Header("Attributes")]
    public float damage = 10f;
    public float fireRate = 1f;
    public float range = 15f;
    public float bulletPenetration = 1f;
    private float fireCountdown = 0f;
    public float turnSpeed = 10f;

    [Header("Upgrading")]
    public float upgradeDamage = 5f;
    public float upgradeFireRate = 0.2f;
    public float upgradeRange = 2f;
    public float upgradeBulletPenetration = 1f;

    [Header("Unity Setup Fields")]
    public string enemyTag = "Enemy";

    public Transform partToRotate;
    public GameObject bulletPrefab;
    public Transform firePoint;



    void Start()
    {
        //UpdateTarget wird 2 mal pro sec ausgeführt
        InvokeRepeating ("UpdateTarget", 0f, 0.5f);
    }


    void UpdateTarget () {
        //Gegner Finden und den nähesten herausfinden
        GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        float shortestDistance = Mathf.Infinity;
        GameObject nearestEnemy = null;

        foreach (GameObject enemy in enemies) {
            float distanceToEnemy = Vector3.Distance (transform.position, enemy.transform.position);
            if (distanceToEnemy < shortestDistance) {
                shortestDistance = distanceToEnemy;
                nearestEnemy = enemy;
            }
        }

        if (nearestEnemy != null && shortestDistance <= range) {
            target = nearestEnemy;
        }else{
            target = null;
        }
    }

    void Update()
    {
        if (target == null) {
            return;
        }

        //Auf den Target schauen
        Vector3 dir = target.transform.position - transform.position;
        Quaternion lookRotation = Quaternion.LookRotation(dir);
        Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
        partToRotate.rotation = Quaternion.Euler (0f, rotation.y, 0f);

        if (fireCountdown <= 0f) {
            Shoot();
            fireCountdown = 1f / fireRate;
        }

        fireCountdown -= Time.deltaTime;
    }

    void Shoot () {
        GameObject bulletGO = (GameObject)Instantiate (bulletPrefab, firePoint.position, firePoint.rotation);
        //Neue Variable Bullet, Name der Variable arrow, arrowGo ist das Gameobject dass instanziert wurde, GetComponent<Bullet> man bekommt das Script Bullet
        RockBullet bullet = bulletGO.GetComponent<RockBullet>();
        if(bullet != null) {
            bullet.Seek(target, damage, bulletPenetration);
        }
    }

    void OnDrawGizmosSelected () {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, range);
    }

    public void Upgrade(int attribute)
    {
        switch (attribute)
        {
            case 0:
                damage += upgradeDamage;
                break;
            case 1:
                fireRate += upgradeFireRate;
                break;
            case 2:
                range += upgradeRange;
                break;
            case 3:
                bulletPenetration += upgradeBulletPenetration;
                break;
        }
    }
}

А вот функции nodeScript:

public GameObject turret;

public GameObject GetTurret()
    {
        return turret;
    }
public void BuildTurret(GameObject turretToBuild)
    {
        if (turret != null){
                //Upgrade Tower oder Zerstören
                Debug.Log("Can't build there! - Feld für Upgrade oder so");
                return;
            }
        turret = (GameObject)Instantiate(turretToBuild, transform.position, transform.rotation);
    }

1 Ответ

0 голосов
/ 25 апреля 2020

возможное решение:

вы определяете абстрактный класс с помощью интерфейса:

using UnityEngine;

public abstract class AbstractTurret : MonoBehaviour, ITurret
{
    public abstract float GetDamage();

}

public interface ITurret
{
    //you put all common method here
    float GetDamage();
}                          

вы создаете свою башню:

public class Cannon : AbstractTurret
{
    public float damage = 10f;

    public void Start(){
    }

    public void Update()
    {
    }

    public override float GetDamage()
    {
        return damage;
    }
}

в своем игровом менеджере вы делаете:

    ITurret turret = (ITurret)GetComponent(typeof(ITurret));
    float d = turret.GetDamage();

после, если вы хотите получить доступ к некоторым свойствам Cannon, вы можете добавить:

        Cannon cannon = (Cannon)turret;
...