9.1 基本概念
这一篇有难度,是塔防非常关键的部分,就是用鼠标在各个方形底座随机摆放 炮塔,这里面需要给我们的大管家GameMaster加点料:
BuildManager需要增加点职能,要知道需要生成那个炮塔类型
大管家也要知道玩家状态,有几条命,手上还有余钱吗,所以加上PlayerStats脚本
9.2 都是代码功夫活
玩家状态:目前就集中在手上的余钱
public class PlayerStats : MonoBehaviour
{
public static int Money; // 玩家受伤的钱
public int startMoney = 100; // 启动资金
public static int Lives; // 总命数
public int startLives = 5;
public static int Rounds; // 记录通过攻击波多少轮次
// Start is called before the first frame update
void Start()
{
Money = startMoney;
Lives = startLives;
Rounds = 0;
}
}
构造一个炮塔装饰类,除了炮塔本体,还有成本
炮塔数据的实体类
[System.Serializable]
public class TurretBlueprint
{
public GameObject prefab; // 要创建的预制类炮塔
public int cost; // 炮塔价钱
}
BuildManager里面登记炮塔预制类,在U3D界面上把Prefab的StdTurret拽到turretToBuild就行
public class BuildManager : MonoBehaviour
{
public static BuildManager instance;
public TurretBlueprint turretToBuild; // 需要指定要用这个工厂类生成的炮塔预制类
private Node selectedNode;
private void Awake()
{
// 构造Singleton类
if (instance != null)
{
return;
}
instance = this;
}
public bool CanBuild { get { return turretToBuild != null; } }
public bool HasMoney { get { return PlayerStats.Money >= turretToBuild.cost; } }
/// <summary>
/// 选择鼠标选中的底座
/// </summary>
/// <param name="node"></param>
public void SelectNode(Node node)
{
if (selectedNode == node)
{
DeselectNode();
return;
}
selectedNode = node;
turretToBuild = null;
}
public void DeselectNode()
{
selectedNode = null;
}
public void SelectTurretToBuild(TurretBlueprint turret)
{
turretToBuild = turret;
DeselectNode();
}
public TurretBlueprint GetTurretToBuild()
{
return turretToBuild;
}
}
生成炮塔的底座容器,这段代码是本章节的主角,其核心就是OnMouseDown里面的部分,请看注释😊
public class Node : MonoBehaviour
{
public Color hoverColor;
public Color noEnoughMoneyColor;
public Vector3 positionOffset; // 微调炮塔坐落在底座的位置
private Renderer rend; // 引用渲染器,用于调整底座颜色
private Color startColor;
[HideInInspector]
public GameObject turret;
[HideInInspector]
public TurretBlueprint turretBlueprint;
[HideInInspector]
public bool isUpgraded = false;
BuildManager buildManager;
void Start()
{
// 获取渲染类,用在鼠标掠过的时候改变底座颜色
rend = GetComponent<Renderer>();
startColor = rend.material.color;
buildManager = BuildManager.instance;
}
public Vector3 GetBuildPosition()
{
return transform.position + positionOffset;
}
private void OnMouseDown()
{
// 如果底座上已经有炮塔,就只是让buildManager选中该底座
if (turret != null)
{
buildManager.SelectNode(this);
return;
}
// 没有指定要生成的炮塔的话,就退出
if (!buildManager.CanBuild)
{
return;
}
// 创建炮塔
BuildTurret(buildManager.GetTurretToBuild());
}
void BuildTurret(TurretBlueprint blueprint)
{
// 如果玩家账上没有钱,则退出
if (PlayerStats.Money < blueprint.cost)
{
Debug.Log("No enough money to build that!");
return;
}
PlayerStats.Money -= blueprint.cost;
// 创建炮塔
GameObject _turret;
_turret = (GameObject)Instantiate(blueprint.prefab, GetBuildPosition(), Quaternion.identity);
Debug.Log("Prefab Name: " + blueprint.prefab);
turret = _turret;
this.turretBlueprint = blueprint;
}
private void OnMouseEnter()
{
if (!buildManager.CanBuild)
{
return;
}
if (buildManager.HasMoney)
{
rend.material.color = hoverColor;
// rend.material.color = Color.blue;
}
else
{
rend.material.color = noEnoughMoneyColor;
// rend.material.color = Color.gray;
}
}
private void OnMouseExit()
{
rend.material.color = this.startColor;
}
}
9.3 客户小余
到目前为止,这个小小的塔防游戏基本上可以玩了,有了敌人,还有可以消灭敌人的炮塔。这时老余欣欣然叫来了小余,这免费的测试白用谁不用啊,另外还能拿到不少宝贵的用户意见呢。
小余也不含糊,家里大人让玩,那还等什么呀。
很快,咱们的免费测试大人就提出意见了:
炮塔要能选
还要多几种威力的炮塔
看不到自己还有多少钱,几条命
不知道下一波攻击什么时候来
不知道坏蛋还有多少血
有的炮塔不想要了,想换威力大的
老余的汗很快就下来了,合着天下的客户都一样,什么要求都是张嘴就来,这是客户的天然文化属性啊!
我们的《和儿子一起编游戏-塔防系列》第一季就到这里,很快老余为了儿子的新要求,会赶出塔防系列第二季,敬请期待。