unity3d 如何使用C#在Unity中的类中创建接口属性,并从该属性访问接口的方法?

7eumitmz  于 2023-04-21  发布在  C#
关注(0)|答案(1)|浏览(168)

我目前正在Unity中创建一个游戏,我想创建一个法术系统。为此,我创建了一个名为ISpell的接口,目前只有一个方法(castSpell)。我还创建了一个名为Fireball的法术,它实现了ISpell接口,允许玩家发射火球。
我的问题如下:我有一个名为能力的职业附加到我的玩家身上,它的唯一目的就是定义启动法术的钥匙,并选择玩家拥有的法术(这对我的问题并不重要)和每个法术的两个属性,第一个属性对应的是启动法术的钥匙,第二个是ISpell类型的属性,不过我无法拖放我的火球术法术,因为该属性不会出现在Unity检查器中,即使它已声明为公共属性。
我不知道我的解决方案是否可行,但我想为我的游戏创建一个灵活且可定制的法术系统。
先谢谢你!以下是我的课程:

public interface ISpell {          
    void castSpell(Transform spawnPoint);          
    float getSpellSpeed();          
    float getSpellLifetime();          
    float getSpellCooldown();  
}
public class FireballSpell : MonoBehaviour, ISpell {
    [Header("Spell Base Settings")]
    public float SpellSpeed = 2.0f;
    public float projectileLifeTime = 10.0f;
    public float cooldown = 1.0f;
    public GameObject spellPrefab;

    [Header("Explosion Settings")]
    public float explosionRadius = 10.0f;
    public GameObject explosionEffect;
    private Vector3 startScale;
    
    
    void Start()
    {
        Destroy(gameObject, projectileLifeTime);
        startScale = explosionEffect.transform.localScale;
    }
    
    public void castSpell(Transform spawnPoint)
    {
        GameObject spellClone = Instantiate(spellPrefab, spawnPoint.position, spawnPoint.rotation);
        Rigidbody rb = spellClone.GetComponent<Rigidbody>();
        rb.AddForce(spawnPoint.forward * spellClone.GetComponent<ISpell>().getSpellSpeed(), ForceMode.Impulse);
    }
    
    void Destroyed(){
        Destroy(gameObject);
    }
    
    void OnDestroy()
    {
        Explode();
    }
    
    private void OnTriggerEnter(Collider other)
    {
        if(other.tag == "Player"){
            return;
        } else {
            Destroy(gameObject);
        }
    }
    
    public void Explode(){
        Vector3 v = new Vector3(explosionRadius, explosionRadius, explosionRadius);
        Instantiate(explosionEffect, transform.position, transform.rotation);
        explosionEffect.transform.localScale  = v;
        Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
        foreach (Collider nearbyObject in colliders)
        {
            if(nearbyObject.tag == "Player" || nearbyObject.tag == "Enemy"){
                Rigidbody rb = nearbyObject.GetComponent<Rigidbody>();
    
                /**Health health = nearbyObject.GetComponent<Health>();
                if (health != null)
                {
                    health.TakeDamage(damage);
                }**/
    
                if(nearbyObject.tag == "Enemy"){
    
                }
            }
        }
    }
    
    private void OnDrawGizmosSelected(){
        Gizmos.DrawWireSphere(this.transform.position, explosionRadius);
    }
    
    public float getSpellSpeed(){
        return SpellSpeed;
    }
    
    public float getSpellLifetime(){
        return projectileLifeTime;
    }
    
    public float getSpellCooldown(){
        return cooldown;
    }

}
public class Abilities: MonoBehaviour {

    public Transform spawnPoint;

    [Header("Spell 1 Settings")]
    public ISpell spell1;
    public KeyCode key1;
    
    void Update()
    {
        if(Input.GetKeyDown(key1))
        {
            spell1.castSpell(spawnPoint);
        }
    }

}
kninwzqo

kninwzqo1#

Unity默认不能序列化接口,可以使用Odin来实现,但实际上我并不推荐。
如果你想在检查器窗口中分配链接,你可以使用一个小技巧。只需将你的ISpell接口替换为基本抽象MonoBehaviour类。然后你就可以在检查器中分配这个链接。

public abstract BaseSpell : MonoBehaviour
{
    abstract public void castSpell(Transform spawnPoint);          
    abstract public float getSpellSpeed();          
    abstract public float getSpellLifetime();          
    abstract public float getSpellCooldown(); 
}

public FireballSpell : BaseSpell 
{ 
    ... 
}

public class Abilities : MonoBehaviour
{
    ...
    public BaseSpell spell1;
    ...
}

相关问题