Unity3D 实现怪物巡逻、按路线行走操作

为了丰富我们的游戏,我们经常会给游戏中的角色(怪物)添加行走路线,本想用 ITweenPath 插件实现,但是一直没有找到合适的办法,因为不知道如何实现实行的获得地形高度,或者如果使用角色控制器移动(CharacterController),怎么使用 ITweenPath 驱动?本人愚笨,自己实现了个(这儿只是使用 ITweenPath 绘制出来的点),也算抛砖引玉,如果读者知道如何更简单的实现方式,还请告之!共同进步!

先来看看最终的效果图:

场景中有两个角色,然后他们会在 ITweenPath 绘制的线上随机移动!下面我们先搭建好测试的场景,如下图:

然后我们使用 ITweenEditor 编辑场景中角色的行进路线,如下图:

后面,就需要我们自己去实现行走的逻辑了,获取 ITweenPath 曲线上的点,前面的文章中提到,详细可以看此链接,然后我们新建立一个 RoleController.cs 文件,然后编写我们的代码,全部代码如下:

using UnityEngine;
using System.Collections;

public class RoleController : MonoBehaviour
{
	public iTweenPath tweenPath;

	/// <summary>
	/// 曲线上面点的个数,点数越多移动越平滑
	/// </summary>
	public int pointSize = 5;

	/// <summary>
	/// 角色移动速度
	/// </summary>
	public float speed = 3f;

	public AnimationClip walkClip;
	public AnimationClip idleClip;

	private Vector3[] pathPositionList;
	private Vector3 pathPoint;

	private Vector3[] positionList;
	private Vector3 nextPoint;
	private Vector3 direction;

	private int moveIndex;
	private bool moveStatus;
	private bool idleStatus;

	private Animation animation;

	void Awake()
	{
		this.pathPositionList = PointController.PointList(tweenPath.nodes.ToArray(), this.pointSize);
		this.animation = this.GetComponent<Animation> ();

		this.moveIndex = 0;
		this.moveStatus = false;
		this.idleStatus = false;

		if (this.pathPositionList.Length > 0)
		{
			this.pathPoint = this.pathPositionList [Random.Range(0, this.pathPositionList.Length)];
		}
	}

	void Start()
	{
		this.transform.position = this.GetTerrainPosition (this.pathPoint);
		this.StartCoroutine(this.SetNextPositionList(0));
	}

	void Update()
	{
		this.SetMoveDirection ();
		this.SetMovePosition ();
	}

	/// <summary>
	/// 设置移动向量
	/// </summary>
	protected void SetMoveDirection()
	{
		if (this.positionList == null) return;
		if (this.moveIndex < this.positionList.Length)
		{
			if(!this.moveStatus)
			{
				this.pathPoint = this.positionList[this.moveIndex];
				this.nextPoint = this.GetTerrainPosition(this.pathPoint);
				this.direction = (this.nextPoint - this.transform.position).normalized * this.speed;

				if(this.direction != Vector3.zero)
				{
					this.transform.rotation = Quaternion.LookRotation(new Vector3(this.direction.x, 0f, this.direction.z));
					this.moveStatus = true;
				}else{
					this.moveIndex ++;
				}
			}
		}else
		{
			if(!idleStatus)
			{
				this.idleStatus = true;
				this.animation.CrossFade (this.idleClip.name);
				this.StartCoroutine(this.SetNextPositionList(5));
			}
		}
	}

	/// <summary>
	/// 设置移动位置
	/// </summary>
	protected void SetMovePosition ()
	{
		if (this.positionList == null) return;

		if (!this.IsArrivePosition ())
		{
			//this.characterController.Move(this.direction * Time.deltaTime); // 可以取消这句,并且注释下面那句,可以使用角色控制器进行移动
			this.transform.position = GetTerrainPosition(this.transform.position + this.direction * Time.deltaTime);
		} else {
			this.transform.position = this.nextPoint;
			this.moveStatus = false;
			this.moveIndex ++;
		}
	}

	protected IEnumerator SetNextPositionList(int sceond)
	{
		if (sceond > 0)
		{
			yield return new WaitForSeconds (5);
		} else {
			yield return null;
		}

		int index = this.GetIndexByList (this.pathPositionList, this.pathPoint);
		if (index != -1)
		{
			int nextIndex = Random.Range(0, this.pathPositionList.Length);
			if(index != nextIndex)
			{
				int beginIndex = index > nextIndex ? nextIndex : index;
				int endIndex = index > nextIndex ? index : nextIndex;

				Vector3[] positionList = new Vector3[endIndex - beginIndex];
				int positionLength = positionList.Length;

				if(index > nextIndex)
				{
					for(int pathIndex = endIndex, positionIndex = 0; pathIndex >= beginIndex && positionIndex < positionLength; pathIndex --, positionIndex ++)
					{
						positionList[positionIndex] = this.pathPositionList[pathIndex];
					}
				}else{
					for(int pathIndex = beginIndex, positionIndex = 0; pathIndex <= endIndex && positionIndex < positionLength; pathIndex ++, positionIndex ++)
					{
						positionList[positionIndex] = this.pathPositionList[pathIndex];
					}
				}

				this.moveIndex = 0;
				this.moveStatus = false;
				this.idleStatus = false;
				this.animation.CrossFade (this.walkClip.name);

				this.positionList = positionList;
			}
		}
	}

	/// <summary>
	/// 获取点帖地位置
	/// </summary>
	/// <returns>The terrion position.</returns>
	/// <param name="position">Position.</param>
	private Vector3 GetTerrainPosition(Vector3 position)
	{
		Vector3 terrainPosition = new Vector3 (position.x, position.y, position.z);
		terrainPosition.y = Terrain.activeTerrain.SampleHeight (terrainPosition);
		return terrainPosition;
	}

	/// <summary>
	/// 是否到达指定位置
	/// </summary>
	/// <returns><c>true</c> if this instance is arrive position; otherwise, <c>false</c>.</returns>
	private bool IsArrivePosition()
	{
		Vector3 currentDirection = (this.nextPoint - (this.transform.position + this.direction * Time.deltaTime)).normalized;
		if (this.CalculateNormalized (currentDirection) == this.CalculateNormalized (this.direction) * -1)
		{
			return true;
		}
		return false;
	}

	/// <summary>
	/// 计算向量标准
	/// </summary>
	/// <returns>The normalized.</returns>
	/// <param name="data">Data.</param>
	private Vector3 CalculateNormalized(Vector3 data)
	{
		Vector3 position = Vector3.zero;
		position.x = data.x >= 0 ? 1 : -1;
		position.z = data.z >= 0 ? 1 : -1;
		return position;
	}

	private int GetIndexByList(Vector3[] positionList, Vector3 position)
	{
		int index = 0;
		foreach (Vector3 item in positionList)
		{
			if(item.x == position.x && item.y == position.y && item.z == position.z) return index;
			index ++;
		}
		return -1;
	}
}

然后我们给场景中的角色挂载 RoleController.cs 脚本,并且设置好相关属性,如下图:

最后运行游戏,就可以看到角色在场景中按线路行走了!

原文链接:http://www.omuying.com/article/43.aspx

时间: 2024-09-30 14:30:28

Unity3D 实现怪物巡逻、按路线行走操作的相关文章

皇室战争 路线行走 (二)

改进了一下,中间的河流,做成第五区域,桥两端 分上下 两个点. 具体做法如下图 先设置10个空对象,按照固定位置排好,L代表左 R 代表右 M代表中,D下U上,都是英文首字母. 比如桥左上端,就是 LUM 左上中,因为桥是中间 .桥右下 就是 RDM 右下中. 这段代表就是把  10个节点的坐标 都保存起来,用单例,这样以后获取就不要 找来找去. GroundVector = new Transform[10]; GameObject GroundVectors = GameObject.Fin

2019最适合自学的unity3d学习路线

不得不说,unity3d是一个解放生产力的游戏引擎,自带了各种编辑器,可以进行一系列的可视化操作.需要注意的是,unity3d适合FPS游戏,物理游戏等中小型的游戏,并不太适合MMO开发.总结了个自己觉得适合一些没有接触过unity3d的朋友的学习路线(非常适合自学哟):此过程假设学习者: 有一定图形学基础,比如清楚3D平移旋转等操作,四元数基本原理,对纹理,材质,灯光等有基本了解. 开发语言不是障碍,即采用何种语言进行开发不是问题. 阅读英文艺术文档没有障碍对于1,如果是计算机专业毕业,一般找

Cocos2d-x 怪物智能AI怪物也有智商----之游戏开发《赵云要格斗》(6)

       这里是Evankaka的博客,欢迎大家前面讨论与交流------       转载请注明出处http://write.blog.csdn.net/postedit/42611031 这几天一直在研究怪物的AI,博客都没怎么更新.本文将主要来讲讲游戏开发中的怪物智能,一个好的游戏一般怪物都要分等级,这样我们游戏玩起来才有意思,怪物如果智商太高,游戏难度大.怪物如果智商太低,游戏玩起来又没有意思.一般好的游戏低级怪物和中级怪物占大部分,高级怪物一般是BOSS级怪物.下面我来讲讲自己对怪

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第八部---怪物出场

/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码:第二可以说明是学习笔记---好人 **3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x */ ***每一步对应的所有代码以及用到的资源都会打包在最后给出 ***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git

扩展Unity3d 组件方法,简化API使用 - C#特性之 Extension Method

在日常使用Unity3d中,经常碰到一些简单操作但是代码却很长的问题,比如变换一个 GameObject的 Y 位置,会按照下面的写法: transform.localPosition = new Vector3 (transform.localPosition.x, transform.localPosition.y + 100, transform.localPosition.z); 转自http://blog.csdn.net/huutu http://www.thisisgame.com

unity3d优化总结篇

转自http://www.unitymanual.com/thread-21597-1-1.html 此总结由自己经验及网上收集整理优化内容 包括:1.代码方面:2.函数使用方面:3.ngui注意方面:4.数学运算方面:5.内存方面:6.垃圾回收方面 等等...本着相互交流 共同进步的原则 好了,总结如下: 1. 尽量避免每帧处理,可以每隔几帧处理一次 比如: [C#] 纯文本查看 复制代码 function Update() { DoSomeThing(); } 可改为每5帧处理一次: [C#

(转)&lt;Unity3D&gt;Unity3D在android下调试

转自:http://blog.csdn.net/zuoyamin/article/details/11827309 一.工具准备 1.JDK——由于android是基于Java平台开发的,jdk是必须要安装的.下载地址:http://www.java.net/download/jdk6/6u10/promoted/b32/binaries/jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe 2.Android SDK——这个就不多说了,要开发a

Unity3D集成TortoiseSVN

无论是个人开发还是团队开发,养成好的版本管理习惯可以大大提高开发效率.常用的版本管理软件一般用SVN或者Git.尽管2者都在用,但是更加偏好SVN一些.安装TortoiseSVN就可以直接将SVN管理软件集成到Windows的Explorer中了.点击鼠标右键就会有SVN的相关菜单,可以非常方便地CheckOut项目以及Commit和Update. 在使用Unity3D开发时,目前主流的代码编辑器(IDE)都会选择Virsual Studio(VS).作为宇宙第一强大的IDE,VS自然也有SVN

使用unity3d需要注意到细节

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. 操作transform.localPosition的时候请小心 移动GameObject是非常平常的一件事情,一下代码看起来很简单: transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0