C# virtual修饰符

定义

virtual 关键字用于修改方法、属性、索引器或事件声明,并使它们可以在派生类中被重写

备注

调用虚拟方法时,将为替代的成员检查该对象的运行时类型。 将调用大部分派生类中的该替代成员,如果没有派生类替代该成员,则它可能是原始成员

virtual 修饰符不能与 staticabstract``private 或 override 修饰符一起使用

比如游戏中的子弹会有很多不同的子弹,但是子弹也会有很多的共性

接下来举一个例子

1.定义子弹积累Bullet

public abstract class Bullet : MonoBehaviour {

    public int bulletId;
    public int userId;
    private Transform target;

    public virtual string idxString { get; set; }

    public virtual void OnHit() {

    }
    public virtual void Shoot() {
        
    }
    public virtual void SetTarget(Transform trans) {
        this.target = trans;
    }
    public virtual float GetSpeed() {
        return 0;
    }

    /// <summary>
    /// 设置子弹生成点以及对应朝向Forward
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="forward"></param>
    public virtual void SetSpawnPoint(Vector3 pos, Vector3 targetPos) {
        this.transform.position = pos;
        this.transform.forward = targetPos - this.transform.position;
    }

}

2.CannonBullet继承Bullet

public sealed class ConnonBullet : Bullet {

    private TrailRenderer[] trailRenderers;
    private Transform trans;
    private Vector3 flyForward;

    private void Start() {
        if (this.GetComponentsInChildren<TrailRenderer>() != null) {
            this.trailRenderers = this.GetComponentsInChildren<TrailRenderer>();
        }
    }

    /// <summary>
    /// 重写子弹生成点以及对应朝向Forward
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="forward"></param>
    public override void SetSpawnPoint(Vector3 pos, Vector3 targetPos) {
        this.trans = this.transform;
        base.SetSpawnPoint(pos, targetPos);
        this.trans.forward = targetPos - this.trans.position;
        this.flyForward = this.trans.forward * this.GetSpeed();
    }

    public override float GetSpeed() {
        return 200f;
    }

}

3.测试脚本

 public GameObject bulletPreffab;
    private Vector3 bulletSpawn;
    private Vector3 hitPoint;

    private void Start() {
        Bullet bullet = Create("子弹名称");
        bullet.bulletId = 01;//父类字段
        bullet.userId = 10001;
        bullet.SetTarget(null);//子类重写方法
        bullet.SetSpawnPoint(this.bulletSpawn, this.hitPoint);
    }


    public Bullet Create(string bulletName) {
        //正常开发需要对象池,以及其他需求
        //这里为了测试先直接生成
        GameObject bullet=null;
        bullet = GameObject.Instantiate(bulletPreffab);
        if (bullet)
            return bullet.GetComponent<Bullet>();
        return null;
    }

总结

1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。

2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。

猜你喜欢

转载自blog.csdn.net/u012909508/article/details/84316352