查看: 7326|回复: 14
收起左侧

[雨松MOMO] Unity3D研究院之游戏开发中的人工智能AI(三十八)

[复制链接]

[雨松MOMO] Unity3D研究院之游戏开发中的人工智能AI(三十八)[复制链接]

雨松MOMO 发表于 2018-1-10 12:18:42 [显示全部楼层] 回帖奖励 |倒序浏览 |阅读模式 回复:  14 浏览:  7326
很久没有写Unity3D相关的东西了,是因为这段时间我深陷一款IOS的软件开发中。不过以后我还是会回归Unity3D游戏开发的。什么语言都在用,生活与工作都挺给力的嚯嚯。今天还是打开了久违的Unity3D编辑器,那我就写点东西吧,今天我想说的是游戏中的人工智能。人工智能这个东西在游戏中是非常重要的,人工智能说简单了就是根据随机的数字让敌人执行一些动作或逻辑,说难了TA需要一个非常复杂的算法,本文我主要说说Unity3D中人工智能的脚本如何来编写。
        首先你应该搞清楚的一点AI脚本属于一个工具类脚本,工具类脚本的含义就是他应当是由策划人员来绑定游戏对象使用的。也就是说AI脚本程序员应当写的非常的灵活,策划人员可以通过修改脚本对外的变量数值接口就能控制其中的敌人AI。接着创建一个c#脚本AI.CS ,如下图所示,目前脚本对外留出枚举接口变量,策划人员在使用这条脚本时选择对应敌人类型即可。(注:这里仅仅是示例,细致的话还可以将很多敌人详细的信息写入,如:攻击速度、技能类型、移动速度、命中率、攻击百分比、等等,但是一定要让你的脚本写的比较灵活,策划人员在外面选择即可完成)因为目前是一个示例,所以我在这里只简单的区分的敌人类型。
  
下面时这段简单AI的脚本
AI.CS
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
//这里是枚举选择敌人类型
public enum EnemyType
{
	Enemy0,
	Enemy1
}
 
public class AI : MonoBehaviour {
 
	//敌人类型枚举 有策划人员选择
	public EnemyType enemyType = EnemyType.Enemy0;
 
	//主角游戏对象
	public GameObject player;
 
	//敌人状态 普通状态 旋转状态 奔跑状态 追击主角状态 攻击主角状态
	private const int EMEMY_NORMAL=0;
	private const int EMEMY_ROTATION=1;
	private const int EMEMY_RUN = 2;
	private const int EMEMY_CHASE = 3;
	private const int EMEMY_ATTACK = 4;
 
	//记录当前敌人状态 根据不同类型 敌人播放不同动画
	private int state;
	//旋转状态,敌人自身旋转
	private int rotation_state;
	//记录敌人上一次思考时间
	private float aiThankLastTime; 
 
	void Start ()
	{
		//初始话标志敌人状态 以及动画为循环播放
		state = EMEMY_NORMAL;
		this.animation.wrapMode = WrapMode.Loop;
	}
 
	void Update ()
	{
		//根据策划选择的敌人类型 这里面会进行不同的敌人AI
		switch(enemyType)
		{
		case EnemyType.Enemy0:
			updateEnemyType0();
			break;
		case EnemyType.Enemy1:
			updateEnemyType1();
			break;
		}
	}
 
	//更新第一种敌人的AI
	void updateEnemyType0()
	{
		//这个AI比较简单, 当主角与他的距离小于10米时,他将始终朝向这主角
		if(Vector3.Distance(player.transform.position,this.transform.position) <= 10)
		{
			this.transform.LookAt(player.transform);
		}
	}
 
	//更新第二种敌人的AI
	void updateEnemyType1()
	{
 
		//判断敌人是否开始思考
		if(isAIthank())
		{
			//敌人开始思考
			AIthankEnemyState(3);
		}else
		{
			//更新敌人状态
			UpdateEmenyState();
		}
	}
 
	int getRandom(int count)
	{
 
		 return new System.Random().Next(count);
 
	}
 
	bool isAIthank()
	{
		//这里表示敌人每3秒进行一次思考
		if(Time.time - aiThankLastTime >=3.0f)
		{
			aiThankLastTime = Time.time;
			return true;
 
		}
		return false;
	}
 
	//敌人在这里进行思考
	void AIthankEnemyState(int count)
	{
		//开始随机数字。
		int d = getRandom(count);
 
		switch(d)
		{
		case 0:
			//设置敌人为站立状态
			setEmemyState(EMEMY_NORMAL);
			break;
		case 1:
			//设置敌人为旋转状态
			setEmemyState(EMEMY_ROTATION);
			break;
		case 2:
			//设置敌人为奔跑状态
			setEmemyState(EMEMY_RUN);
			break;
		}
 
	}
 
	void setEmemyState(int newState)
	{
		if(state == newState)
			return;
		state = newState;
 
		string animName = "Idle";
		switch(state)
		{
		case EMEMY_NORMAL:
			animName  =  "Idle";
			break;
		case EMEMY_RUN:
			animName  =  "Run";
			break;
		case EMEMY_ROTATION:
			animName  =  "Run";
			//当敌人为旋转时, 开始随机旋转的角度系数
			rotation_state = getRandom(4);
			break;
		case EMEMY_CHASE:
			animName  =  "Run";
			//当敌人进入追击状态时,将面朝主角方向奔跑
			this.transform.LookAt(player.transform);
			break;
		case EMEMY_ATTACK:
			animName  =  "Attack";
			//当敌人进入攻击状态时,继续朝向主角开始攻击砍人动画
			this.transform.LookAt(player.transform);
			break;
		}
 
		//避免重复播放动画,这里进行判断
		if(!this.animation.IsPlaying(animName))
		{
			//播放动画
			this.animation.Play(animName);
		}
 
	}
 
	//在这里更新敌人状态
	void UpdateEmenyState()
	{
		//判断敌人与主角之间的距离
		float distance = Vector3.Distance(player.transform.position,this.transform.position);
		//当敌人与主角的距离小于10 敌人将开始面朝主角追击
		if(distance <= 10)
		{
			//当敌人与主角的距离小与3 敌人将开始面朝主角攻击
			if(distance <= 3)
			{
				setEmemyState(EMEMY_ATTACK);
			}else
			{
			    //否则敌人将开始面朝主角追击
				setEmemyState(EMEMY_CHASE);
			}
 
		}else
		{
			//敌人攻击主角时 主角迅速奔跑 当它们之间的距离再次大于10的时候 敌人将再次进入正常状态 开始思考
			if(state == EMEMY_CHASE || state == EMEMY_ATTACK)
			{
				setEmemyState(EMEMY_NORMAL);
			}
 
		}
 
		switch(state)
		{
		case EMEMY_ROTATION:
			//旋转状态时 敌人开始旋转, 旋转时间为1秒 这样更加具有惯性
			transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.Euler(0,rotation_state * 90,0),  Time.deltaTime * 1);
			break;
		case EMEMY_RUN:
			//奔跑状态,敌人向前奔跑
			transform.Translate(Vector3.forward *0.02f);
			break;
		case EMEMY_CHASE:
			//追击状态 敌人向前开始追击
			transform.Translate(Vector3.forward *0.02f);
			break;
		case EMEMY_ATTACK:
 
			break;
		}
 
	}
}
如下图所示,我们在游戏世界中添加两个敌人,此时给敌人们都绑定上AI的脚本,编辑器中设置不同的敌人类型,敌人执行各自的生命周期,当你控制主角与接近敌人时,敌人开始追击你并且向你展开攻击。
  • 本文固定链接: [url=http://www.xuanyusong.com/archives/1840]http://www.xuanyusong.com/archives/1840

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
+1
7332°C
14
  • 会飞的日记本
  • freeopen
  • lovegame2018
  • HultFang
  • XIAOWEN
过: 他们
因分享而快乐,学习以自强!
会飞的日记本 发表于 2018-1-10 16:15:16 显示全部楼层
感谢楼主分享ing
因分享而快乐,学习以自强!
freeopen 发表于 2018-1-10 17:06:31 显示全部楼层
嗯,不错.
因分享而快乐,学习以自强!
lovegame2018 发表于 2018-1-11 09:26:29 显示全部楼层
好文章,收藏了。谢谢楼主分享。
因分享而快乐,学习以自强!
HultFang 发表于 2018-1-11 10:08:32 显示全部楼层
好文章,收藏了。谢谢楼主分享。
因分享而快乐,学习以自强!
XIAOWEN 发表于 2018-1-11 10:24:24 显示全部楼层
demo仅仅是一个示例,主要希望大家明白一个道理。
因分享而快乐,学习以自强!
泰课_robin 发表于 2018-1-11 12:43:16 显示全部楼层
XIAOWEN 发表于 2018-1-11 10:24
demo仅仅是一个示例,主要希望大家明白一个道理。

回复很到位
来自苹果客户端来自苹果客户端
因分享而快乐,学习以自强!
泰课_robin 发表于 2018-1-11 12:44:48 显示全部楼层
HultFang 发表于 2018-1-11 10:08
好文章,收藏了。谢谢楼主分享。

用手机app收藏很方便
来自苹果客户端来自苹果客户端
因分享而快乐,学习以自强!
cccpjc 发表于 2018-1-11 15:58:07 显示全部楼层
谢谢分享!!!!!
因分享而快乐,学习以自强!
persistence2017 发表于 2018-1-12 15:46:07 显示全部楼层
666666666666666666666
因分享而快乐,学习以自强!
星陨尘心_clw 发表于 2018-1-12 16:07:57 显示全部楼层
万分感谢楼主分享
因分享而快乐,学习以自强!
茶LZJE 发表于 2018-1-12 18:27:27 显示全部楼层
为您的才华点赞
因分享而快乐,学习以自强!
追逐浪尖 发表于 2018-1-30 17:08:55 显示全部楼层
人工智能,正在学习中
因分享而快乐,学习以自强!
AdvancePikachu 发表于 2018-3-22 11:56:29 显示全部楼层
学习了,感谢分享!
因分享而快乐,学习以自强!
白麟 发表于 2018-6-12 13:09:30 显示全部楼层
感謝分享
因分享而快乐,学习以自强!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

VR/AR版块|Unity3d|Unreal4|新手报道|小黑屋|站点地图|沪ICP备14023207号-9|【泰斗社区】-专注互联网游戏和应用的开发者平台 ( 沪ICP备14023207号-9 )|网站地图

© 2001-2013 Comsenz Inc.  Powered by Discuz! X3.4

1
QQ