前言
现在想想,设计角色这块,接口确实没有必要。怪我想的不全
流程
设计一个所有角色都应该具有属性与行为的基类 RoleBase
public class RoleBase : MonoBehaviour,Action
{
//基础属性如血量
[SerializeField]
private double blood;
//方便以后某种实现的调用 --
//每个角色攻击的方式难免有差异,所有要使用虚函数 让子类(角色)来决定
public virtual void Attack()
{
}
//受伤都是一样的 不用管
public void Hurt(float attackforce)
{
blood -= attackforce;
}
}
实现一个角色 继承自RoleBase
public class Role1 : RoleBase
{
//Attack方法是你要怎么实现这个角色攻击方式的实现代码
public override void Attack()
{
//这是一个攻击方式实现的例子
//该例子 就像放了一个炸弹在一个玩家怀里,然后炸了
//示例 下面的Physics是以玩家为中心 半径为5的圆心 获取所有的具有Collider脚本的对象的Collider
var colliders = Physics.OverlapSphere(transform.position, 5f);
//将该范围内的所有玩家进行扣血
for(int i=0; i<colliders.Length; i++)
{
//我们可以通过Collider对象获取它的gameObject,从而再从这个gameObject获取它身上具有的脚本(组件)
//下面的例子就是 我们通过检测到的collider对象获取它的gameObject,再从这个gameObject获取它身上的RoleBase或是从它派生出来的子类的脚本(为了实现能对多种角色进行受伤行为,我们需要获取他们都具有的基类RoleBase)
RoleBase roleBase = colliders[i].gameObject.GetComponent<RoleBase>();
//再让每个玩家扣血300;
if(roleBase != null )
roleBase.Hurt(300f);
}
}
//以上的代码下实现这就是一种实现攻击的方式
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Role2 : RoleBase
{
public override void Attack()
{
//实现某个在该角色下
//执行某个你所决定的攻击方式
}
}
测试 如果还是不理解为什么要这样设计请看
一个Controller脚本
public class Controller : MonoBehaviour
{
//我们通过下面的形式,能够实现不同角色的切换
public RoleBase Role;
//用于调试的参数
public bool attack;
//当我在inspector窗口勾选bool时 发生该角色的攻击
private void Update()
{
if (attack)
{
attack = false;
Role.Attack();
}
}
}
开始调试
我建立了三个物体(GameObject)并且 Cube装载了Role1脚本,Cube(1)装载了Role2脚本,Controller装载脚本



运行

当我勾选Attack


Role执行了继承它的子类Role1重写的攻击方法
我们发现所有装载了具有Role或是它的派生类(本案只用了Role的派生类Role1和Role2)


博客围绕C#开发中的角色设计展开。先指出设计角色时接口并非必要,接着介绍设计流程,包括创建基类RoleBase及继承该基类的角色类,还通过Controller脚本进行测试,运行后发现装载Role或其派生类的对象能执行相应方法,展示了所需的设计模式。
315





