Unity实战 RTS3D即时战略游戏开发(十) 可建造地点标示

     大家好,我是Zander,我们接着来开发Rts3D即时战略游戏开发。这一节我们来讲在地图上哪些区域可以建造建筑,哪些地方不可以。

     建筑在地形上跟随鼠标,但是并没有标记指示在哪里可以建造,我们希望,如果不能建造就显示红色,如果能建造就显示绿色。

 首先在RTSManager中添加一个特别的函数   ,进入RTSManager并编辑这个脚本,添加一个新的方法:

public bool IsGameObjectSafeToPlace(GameObject go)
	{
return true;
}
这里暂时不实现这个函数,只是看它的表现;

   接着在FindBuildingSite脚本中能让物体显示为红或绿,这里我们需要定义一些变量,来实现功能:如下:

using UnityEngine;
using System.Collections;

public class FindbuildingSite : MonoBehaviour {

	Renderer rend;  //存储Render 这样可以改变颜色并恢复
	Color Red = new Color (1, 0, 0, 0.5f);  //定义不可建区域红色
	Color Green = new Color (0, 1, 0, 0.5f); //定义可建区域绿色

	void Start()
	{
		rend = GetComponent<Renderer> ();
	}

	// Update is called once per frame
	void Update () {
		var tempTarget = RtsManager.Current.ScreenPointToMapPosition (Input.mousePosition);
		if (tempTarget.HasValue == false)
			return;

		transform.position = tempTarget.Value;

		if (RtsManager.Current.IsGameObjectSafeToPlace (gameObject)) //判断此区域是否可建造建筑
        {
			rend.material.color = Green;
		} else {
			rend.material.color = Red;
		}
	}
}
现在返回到RTSManager重新写一下IsGameObjectSafeToPlace这个函数,为了检测是否可建,我要判断每一个顶点看它是不是在可通过的地形上,首先要得到顶点,取得MeshFilter,从中获得mesh,接下来还要取得哪些潜在可能阻碍建造的障碍物列表,例如建筑。代码如下:


public bool IsGameObjectSafeToPlace(GameObject go)
	{
		var verts = go.GetComponent<MeshFilter> ().mesh.vertices;  //获取全部顶点

		var obstacles = GameObject.FindObjectsOfType<NavMeshObstacle> ();  //得到障碍物集合
		var cols = new List<Collider> ();
		foreach (var o in obstacles) {
			if (o.gameObject != go) {
				cols.Add (o.gameObject.GetComponent<Collider> ());
			}
		}
        //检测每一个顶点,对于每个顶点都要检测其是否在可通过的地形上,
		foreach (var v in verts) {
			NavMeshHit hit;
			var vReal = go.transform.TransformPoint (v);   //取得顶点的世界位置坐标,
			NavMesh.SamplePosition (vReal, out hit, 20, NavMesh.AllAreas);

            //接下来需要检测顶点是不是在核实的XZ平面或碰撞体内,因为不关心离地多高,所以可以忽略Y轴,只关心点在不在障碍物内,
			bool onXAxis = Mathf.Abs (hit.position.x - vReal.x) < 0.5f;  //如果这两个点的距离小于0.5  我们认为在 X 轴上是可行的
            bool onZAxis = Mathf.Abs(hit.position.z - vReal.z) < 0.5f;   //如果这两个点的距离小于0.5  我们认为在 Z 轴上是可行的
			bool hitCollider = cols.Any (c => c.bounds.Contains (vReal));  //如果任何一个碰撞体的范围内有这个顶点,则HitCollider为true

			if (!onXAxis || !onZAxis || hitCollider) {
				return false;
			}
		}

		return true;
	}

保存代码,运行Unity,则会发现我们把建筑拖拽到山上就变红,拖到平地就会变绿。

    现在我们来实现鼠标再次点击时建造建筑,我们找到FindBuildingSite脚本,并修改Start方法,为确保建筑物被认为或意外的销毁后要恢复操作,在Update内判断是否可建

using UnityEngine;
using System.Collections;

public class FindbuildingSite : MonoBehaviour {

	public float Cost = 200;   //建造费用
	public float MaxBuildDistance = 30;  //建造距离
	public GameObject BuildingPrefab;    //建筑预设
	public PlayerSetupDefinition Info;   //玩家信息
	public Transform Source;           //资源的位置坐标,用来判断是否可建造

	Renderer rend;
	Color Red = new Color (1, 0, 0, 0.5f);
	Color Green = new Color (0, 1, 0, 0.5f);

	void Start()
	{
		MouseManager.Current.enabled = false;
		rend = GetComponent<Renderer> ();
	}

	// Update is called once per frame
	void Update () {
		var tempTarget = RtsManager.Current.ScreenPointToMapPosition (Input.mousePosition);
		if (tempTarget.HasValue == false)
			return;

		transform.position = tempTarget.Value;

		if (Vector3.Distance (transform.position, Source.position) > MaxBuildDistance)   //判断和无人机的位置,如果太远不可建
        {
			rend.material.color = Red;
			return;
		}

		if (RtsManager.Current.IsGameObjectSafeToPlace (gameObject)) {
			rend.material.color = Green;
			if (Input.GetMouseButtonDown (0)) //鼠标再次点击时建造建筑
            {   
				var go = GameObject.Instantiate (BuildingPrefab);
				go.transform.position = transform.position;
				Info.Credits -= Cost;  //扣除费用
				go.AddComponent<Player> ().Info = Info;
				Destroy (this.gameObject);
			}
		} else {
			rend.material.color = Red;
		}
	}

	void OnDestroy()
	{
		MouseManager.Current.enabled = true;
	}

}

返回Unity修改CreateBuildingAction脚本,如下:

using UnityEngine;
using System.Collections;

public class CreateBuildingAction : ActionBehavior {

	public float Cost = 0;     //建筑花费 
	public GameObject BuildingPrefab;//建筑预设
	public float MaxBuildDistance = 30; //最远可建造距离


	public GameObject GhostBuildingPrefab;
	private GameObject active = null;

	public override System.Action GetClickAction ()
	{
		return delegate() {
			var player = GetComponent<Player>().Info;
			if (player.Credits < Cost)
			{
				Debug.Log("Not enough, this costs " + Cost);
				return;
			}
            //建造建筑逻辑处理
			var go = GameObject.Instantiate(GhostBuildingPrefab);
			var finder = go.AddComponent<FindbuildingSite>();
			finder.BuildingPrefab = BuildingPrefab;
			finder.MaxBuildDistance = MaxBuildDistance;
			finder.Info = player;
			finder.Source = transform;
			active = go;
		};
	}

	void Update()
	{
		if (active == null)
			return;

		if (Input.GetKeyDown (KeyCode.Escape)) //取消建造建筑
			GameObject.Destroy (active);
	}

	void OnDestroy()
	{
		if (active == null)
			return;

		Destroy (active);
	}
}

接下来我们来为建筑添加一个可以生产金币的功能,新建Earning脚本:

using UnityEngine;
using System.Collections;

public class Earnings : MonoBehaviour {

	public float CreditsPerSecond = 1;  //每秒生产金币数量 
	private PlayerSetupDefinition player;  //所归属玩家信息  

	// Use this for initialization
	void Start () {
		player = GetComponent<Player> ().Info;   //得到玩家信息
	}
	
	// Update is called once per frame
	void Update () {
		player.Credits += CreditsPerSecond * Time.deltaTime;  //生产金币
	}
}
    好了,这一章就写到这,这是源码地址:链接:http://pan.baidu.com/s/1pLVkU8N 密码:xbe2

欢迎大家加入QQ群:280993838  或者关注我的公众号:








  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity 2D与3D手机游戏开发实战PDF》是一本关于使用Unity引擎开发手机游戏的实用指南。本书以深入浅出的方式介绍了Unity引擎的使用方法,帮助读者从零开始开发出精美的2D和3D手机游戏。 首先,本书详细介绍了Unity引擎的基本概念和界面,使读者能够迅速上手。同时,书中还介绍了Unity的2D和3D游戏开发工具,包括场景编辑器、动画编辑器、物理引擎等,帮助读者了解如何创建游戏场景、设计角色动画,以及添加游戏物理效果。 其次,本书提供了实战项目,通过逐步演示的方式,引导读者完成一个完整的2D或3D手机游戏。通过跟随书中的教程,读者可以学习到游戏开发的整个流程,包括设计游戏关卡、实现游戏逻辑、优化游戏性能等。 本书还介绍了一些实用的游戏开发技巧和经验,帮助读者解决常见的问题和挑战。例如,如何处理碰撞检测、如何优化游戏帧率等。这些技巧和经验对于开发高质量的手机游戏非常重要。 最后,本书还提供了一些额外的资源和工具,例如一些常用的插件和脚本,以及一些游戏美术资源,帮助读者加快游戏开发的速度。 总而言之,通过《Unity 2D与3D手机游戏开发实战PDF》,读者可以系统地学习Unity引擎的使用方法,了解手机游戏开发的整个流程,并且获得一些实用的技巧和工具,帮助他们开发出优质的手机游戏作品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值