• 各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei。 首先博主要自我反省,过了这么久才来更新博客,这段时间主要是在忙着写期末的作业,所以博主基本上没有空闲时间来...

           各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei

           首先博主要自我反省,过了这么久才来更新博客,这段时间主要是在忙着写期末的作业,所以博主基本上没有空闲时间来研究技术,希望大家谅解啊。有时候,博主会不由自主地想,如果当初选择了计算机专业,此时此刻,我可能会有更多的时间来和大家分享我在学习过程中的感悟吧,有时候博主感觉自己很孤独,在身边找不到和自己志同道合对技术感兴趣的人,这可能是博主在大学里最大的遗憾了,一个人的成长环境很重要,当你无法改变身边的环境的时候,你只能努力地改变自己,每当博主对自己说这句话的时候,博主总是一个静静地像现在这样敲写代码,做自己喜欢的事情是幸福的事情。好了,闲话有空再叙,我们正式开始今天的内容。相信大多数的80后、90后一定对《魂斗罗》这款游戏感到熟悉吧,这款游戏可以说是FC时代引领射击类游戏潮流的一款经典之作,以致于其设计深刻影响到了像后来的《合金弹头》等游戏。这个世界上有很多经典的东西,即使时过境迁永远无法被超越。博主在移动平台上看到这款游戏后,果断下载重温了这款经典游戏。作为一名有追求的游戏设计人员,我们应该在玩游戏的过程中有所收获,积极寻找可以作为我们在技术领域研究的东西,博主的博客几乎都是这么写下来的,除非是有针对性地学习某些东西,所以呢,就有了这篇文章。

           好了,不卖关子了,大家在玩《魂斗罗》的时候一定知道游戏中有一种追踪弹吧,这种炮弹会随着玩家位置的改变而改变,就像我们在某些军事题材的电影中经常看到的镜头一样,我方战斗机将敌机目标锁定后发射炮弹,炮弹就会对敌机紧追不舍并最最终摧毁敌机。可是不管影视作品特效如何炫酷夺目,最终留给我们的就是华丽的特效背后蕴藏的原理。在游戏开发领域,这种技术称为追踪算法,它是属于AI的一个范畴。常见的追中算法主要有三种,即坐标追踪、视线追踪、拦截追踪。下面呢,我们来分别讲解这三种不同的追踪算法:

           一、坐标追踪

          坐标追踪是最简单、最基本的一种追踪算法,如图,


         其基本思路是根据追踪目标的坐标来改变追踪物体的坐标,使两者间距离缩短。举一个简单地例子,假设我们使用二维坐标mPosition来表示追踪物体的坐标,使用mTargetPos来表示追踪目标的坐标,则坐标追踪的算法可以简单表示成下面的代码:

    if(mPosition.x<mTargetPos.x) mPosition.x+=Speed*Time.deltaTime;
    if(mPosition.x>mTargetPos.x) mPosition.x-=Speed*Time.deltaTime;
    if(mPosition.y<mTargetPos.y) mPosition.y+=Speed*Time.deltaTime;	
    if(mPosition.y>mTargetPos.y) mPosition.y-=Speed*Time.deltaTime;
    	
         二、视线追踪,主要是指每一时刻都追踪者会沿着被追逐者之间的直线方向运动。如图所示:


            由图易知,该算法的关键是求解两个位置间的连线。由向量的知识我们知道这条直线可以通过向量可以通过向量a-向量b得到。此时追踪者的速度应该满足约束条件:

            水平分速度Vx/垂直分速度Vy=c向量的水平分量/c向量的垂直向量。

             

            三、拦截追踪,拦截追踪是在前两种方法的基础上发展而来的一种方法,如果考虑的是追踪目标太远,如果两者者速度一样,或者相差不大,有可能很难追上。如图


            此时,对于追踪物体而言,它只需要知道追踪目标的位置、方向与速度,就会计算一个最佳的拦截位置,且所需要的时间最短。我们假设最佳拦截点是S2,由速度与位移的关系很容易知道 S2=Sp+t*V。其中t是追踪者追上猎物的时间。接下来问题变为一个简单的追击问题,求追击时间t。

           首先我们建立追踪者与猎物的速度向量Va与Vp,及位置向量Sa与Sp。  设速度差向量 Vd =Vp-Va 。称为靠拢速度。 设距离差向量 Sd =Sp-Sa 。称为靠拢距离。  于是,靠拢时间 t=|Sd|/|Vd| 。即路程除以速度等于时间。  套用公式S2=Sp+t*V 就得到了拦截点S2,剩下的过程就与视线追踪一样。

          好了,在理解了追踪算法的基本原理以后,下面我们以一个最简单的例子来演示今天的内容。首先我们在Unity3D中建立一个简单地场景,如图所示:


           我们采取正交投影的方式来实现一个2D场景,场景中红色的方块为目标物体,绿色的方块为追踪物体。我们这里采取的是视线追踪的方法。我们首先来为追踪物体创建脚本Follow.cs。脚本定义如下:

    using UnityEngine;
    using System.Collections;
    
    public class Follow : MonoBehaviour {
    
    	//追踪的目标物体
    	public Transform Target;
    	//两个物体间的最小距离
    	public float MinDistance=1F;
    	//两个物体间的最大距离
    	public float MaxDistance=5F;
    	//定义追踪的速度
    	public float Speed=0.25F;
    	//定义追踪物体的坐标
    	private Vector2 mPosition;
    	//定义目标物体的坐标
    	private Vector2 mTargetPos;
    	//是否在追踪
    	private bool isFollow=false;
    
    	void Start () 
    	{
    		mPosition=new Vector2(transform.position.x,transform.position.y);
    		mTargetPos=new Vector2(Target.transform.position.x,Target.position.y);
    	}
    
    	void Update () 
    	{
    	  //获取目标物体的位置
    	  mTargetPos=new Vector2(Target.transform.position.x,Target.position.y);
    	  //如果追踪物体与目标物体之间距离大于等于最大距离,则开始追踪
    	  if(Vector2.Distance(mPosition,mTargetPos)>=MaxDistance)
    	  {
    			isFollow=true;
    	  }
    	  //如果追踪物体与目标物体之间距离小于等于最小距离,则停止追踪
    	  if(Vector2.Distance(mPosition,mTargetPos)<=MinDistance)
    	  {
    			isFollow=false;
    	  }
    	  //如果开始追踪,则执行下面的代码
    	  if(isFollow)
    	  {
    			//计算坐标值
    			if(mPosition.x<mTargetPos.x) mPosition.x+=Speed*Time.deltaTime*Mathf.Abs(Mathf.Cos(getAngle()));
    			if(mPosition.x>mTargetPos.x) mPosition.x-=Speed*Time.deltaTime*Mathf.Abs(Mathf.Cos(getAngle()));
    			if(mPosition.y<mTargetPos.y) mPosition.y+=Speed*Time.deltaTime*Mathf.Abs(Mathf.Sin(getAngle()));
    			if(mPosition.y>mTargetPos.y) mPosition.y-=Speed*Time.deltaTime*Mathf.Abs(Mathf.Sin(getAngle()));
    			//改变追踪物体的坐标
    			transform.position=new Vector3(mPosition.x,mPosition.y,0);
    	  }
    	}
    
    
    	private float getAngle()
    	{
    		float angle=0;
    		//获取水平方向与竖直方向的变化量
    		float deltaX=mTargetPos.x-mPosition.x;
    		float deltaY=mTargetPos.y-mPosition.y;
    		//计算角度
    		if(deltaX>0 && deltaY>0)
    			angle= Mathf.Atan(deltaY/deltaX);
    		if(deltaX<0 && deltaY>0)
    			angle= Mathf.PI-Mathf.Atan(deltaY/deltaX);
    		if(deltaX<0 && deltaY<0)
    			angle= Mathf.PI+Mathf.Atan(deltaY/deltaX);
    		if(deltaX>0 && deltaY<0)
    			angle= 2*Mathf.PI-Mathf.Atan(deltaY/deltaX);
    		if(deltaX==0)
    		{
    			angle=Mathf.PI/2;
    		}
    		if(deltaY==0)
    		{
    			angle=0;
    		}
    		return angle;
    	}
    }
    
          在这段脚本中,我们定义了一个getAngle()方法,该方法用于获取追踪物体与目标物体连线与X轴正方向所成的夹角。这里主要用到三角函数知识,大家可以再温习下以前学过的知识,无论是程序设计还是游戏开发,数学都应该是我们最应该掌握的东西。好了,通过角度计算,我们可以将速度分解到水平和垂直两个方向,从而保证视线追踪中的约束条件成立。如果我们将getAngle()方法从脚本中去除,则这就是最简单的坐标追踪,希望大家自己去探讨和研究啊,如果博主有时间的话,会将三种算法的代码都展示出来的,希望大家继续关注我的博客啊。呵呵。好了,接下来,我们来为追踪目标创建一个脚本,以便玩家可以控制追踪目标躲避追踪。脚本定义如下:

    using UnityEngine;
    using System.Collections;
    
    public class Control : MonoBehaviour {
    
    	//定义移动的速度
    	public float Speed=0.25F;
    	//定义当前位置
    	private float mX,mY;
    	void Start () 
    	{
    		mX=transform.position.x;
    		mY=transform.position.y;
    	}
    
    	void Update () 
    	{
    	  if(Input.GetKey(KeyCode.A))
    	  {
    			mX-=Speed*Time.deltaTime;
    	  }
    	  if(Input.GetKey(KeyCode.D))
    	  {
    			mX+=Speed*Time.deltaTime;
    	  }
    	  if(Input.GetKey(KeyCode.W))
    	  {
    			mY+=Speed*Time.deltaTime;
    	  }
    	  if(Input.GetKey(KeyCode.S))
    	  {
    			mY-=Speed*Time.deltaTime;
    	  }
    	  transform.position=new Vector3(mX,mY,0);
    	}
    }
    

             好了,下面我们来测试一下程序运行的效果:

     

            不知道为什么录制的GIF动画看不到追踪物体,囧啊,不过博主可以负责任地对大家说,程序没什么问题,哈哈。

            好了,今天的内容就是这样了,希望大家喜欢,如果大家希望继续在《魂斗罗》游戏中寻找有趣的设计,请关注我的下一篇博客:Unity3D游戏开发之从《魂斗罗》游戏说起(下) 。再次感谢大家关注我的博客,谢谢。


    每日箴言:你专注于一个方向,终会比别人走得远些。




       喜欢我的博客请记住我的名字:秦元培,我博客地址是blog.csdn.net/qinyuanpei。
       转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/29891859



    展开全文
  • unity3d粒子系统之行星带 2018-05-28 01:38:08
    Unity3d实战之粒子系统 选题要求 参考 http://i-remember.fr/en 这类网站,使用粒子流编程控制制作一些效果, 如“粒子光环” 实现效果 静态图 动态图 知识准备 粒子系统有许多大模块,比如最常用的...
  • Unity3d-粒子光环特效 2018-05-29 17:17:55
    要求 ... 当鼠标hover到图一中间的+号圆圈中间时,光环会收缩成图二的状态,具体效果可自行前往网站体验~ 我们需要模仿这个效果并尝试用粒子流编程控制来实现。 ...光环在收缩前较为分散,位于光环中间的部分粒子较...
  • Unity3d_Stats和优化 2015-06-03 00:09:50
    一,Unity3D 渲染统计窗口 Game视窗的Stats去查看渲染统计的信息: 1、FPS fps其实就是 frames per second,也就是每一秒游戏执行的帧数,这个数值越小,说明游戏越卡。   2、Draw calls batching...
  • 在FPS游戏中,人物控制十分重要。人物控制包括,人物行走,跳跃,人物跟随镜头旋转,人物的右手(持枪部位)根据鼠标旋转而旋转。 首先,我们来看看如何使人物进行移动,在这里我使用了Sphere和Capsule作为身体,将...
  • Unity3D - 详解Quaternion类(二) OK,不做引子了,接上篇Unity3D - 详解Quaternion类(一)走起! 四、Quaternion类静态方法 Quaternion中的静态方法有9个即:Angle方法、Dot方法、Euler方法、F...
  • Unity3D中。Vector3.Dot表示求两个向量的点积;Vector3.Cross表示求两个向量的叉积。 点积计算的结果为数值,而叉积计算的结果为向量。两者要注意差别开来。在几何数学中:1.点积 点积的计算方式为: a·b=|a|·...
  • 讨论的前提是,假设目标是在3D空间里以匀速直线方式运动。 1.直线弹道 在不考虑重力和空气阻力影响的情况下,子弹的弹道呈直线运动。这种情况下,其实是个纯平面几何空间的问题,不需要微积分和线代知识。
  • Unity3D - 详解Quaternion类 2017-12-21 16:12:11
    一、简介 Quaternion又称四元数,由x,y,z和w这四个分量组成,是由爱尔兰数学家威廉·卢云·哈密顿在1843年发现的数学概念。...关于四元数的性质、与旋转的关系、球型线性插值的介绍,请阅读3D游戏与计算机
  • Unity3D中,Vector3.Dot表示求两个向量的点积;Vector3.Cross表示求两个向量的叉积。 点积计算的结果为数值,而叉积计算的结果为向量。两者要注意差别开来。 在几何数学中: 1.点积 点积的计算方式为:...
  • Unity3D学习——粒子光环 2018-05-29 21:26:05
    本周的作业要求是使用粒子流编程控制制作一些效果,我则是参考以前师兄的成果制作了一个粒子光环效果。 创建新项目,首先在场景菜单中新建一个空对象,命名为ParticleRing。然后,再为这个对象增添一个子对象,子...
  • 软件工程
  • 8.3.3 Euler方法:欧拉角对应的四元数 基本语法:(1)public static Quaternion Euler(Vector3 euler); (2)public static Quaternion Euler(float x, float y, float z); 功能说明:此方法用于返回欧拉角...
  • 由于颇受暗黑破坏神美工的影响,最近都在研究怎么制作场景地图之类的。   那么今日讲的模型高光虽然和地图无关,但是也涉及到一些美工的知识,尤其是shader。 ...按照国际惯例,先贴一张图饱饱眼福。...
  • 文章目录
  • 目标:创建一个立方体网格代码支持立方体的旋转,缩放,位移,学会使用变换矩阵创建一个简单的摄像机投影 这个是渲染基础教程的第一部分。主要讲解了变换矩阵。为了了解变换矩阵,首先我们需要知道什么是网格,了解...
  • Unity3D 脚本参考 2012-01-19 14:55:54
    Unity3D 脚本中文参考 (1) 这是一个关于Unity内部脚本如何工作的简单概览。 Unity内部的脚本,是通过附加自定义脚本对象到游戏物体组成。在脚本对象内部不同的函数被特定的事件调用。最常用的列在下面: Update...
1 2 3 4 5 ... 8
收藏数 155
精华内容 62