定义
virtual
关键字用于修改方法、属性、索引器或事件声明,并使它们可以在派生类中被重写
备注
调用虚拟方法时,将为替代的成员检查该对象的运行时类型。 将调用大部分派生类中的该替代成员,如果没有派生类替代该成员,则它可能是原始成员
virtual
修饰符不能与 static
、abstract``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重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。