1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 对金玺曾版《Unity3D手机游戏开发》第三章“第一人称射击游戏”修改 使支持僵尸连续攻击

对金玺曾版《Unity3D手机游戏开发》第三章“第一人称射击游戏”修改 使支持僵尸连续攻击

时间:2020-05-28 01:28:55

相关推荐

对金玺曾版《Unity3D手机游戏开发》第三章“第一人称射击游戏”修改 使支持僵尸连续攻击

我个人觉得这本书写的至少很和我口味,而且他的光盘资料也很详尽,比如,一个实例,不仅有一个完整的实现工程,还有一份供作练习的工程(该工程中没有要练习的部分,而资源啥的都有),让人感觉很好。

这本书下载电子版也很方便,比如:/detail/u012337666/8402165。

我接下来具体说说自己对 第三章“第一人称射击游戏”中的改动。

先上改动前的源代码:

using UnityEngine;using System.Collections;[AddComponentMenu("Game/Enemy")]public class Enemy : MonoBehaviour {// Transform组件Transform m_transform;//CharacterController m_ch;// 动画组件Animator m_ani;// 寻路组件NavMeshAgent m_agent;// 主角Player m_player;// 角色移动速度float m_movSpeed = 0.5f;// 角色旋转速度float m_rotSpeed = 120;// 计时器float m_timer=2;// 生命值int m_life = 15;// 成生点protected EnemySpawn m_spawn;// Use this for initializationvoid Start () {// 获取组件m_transform = this.transform;m_ani = this.GetComponent<Animator>();m_agent = GetComponent<NavMeshAgent>();// 获得主角m_player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();}// 初始化public void Init(EnemySpawn spawn){m_spawn = spawn;m_spawn.m_enemyCount++;}// 当被销毁时public void OnDeath(){//更新敌人数量m_spawn.m_enemyCount--;// 加100分GameManager.Instance.SetScore(100);// 销毁Destroy(this.gameObject);}// Update is called once per framevoid Update () {// 如果主角生命为0,什么也不做if (m_player.m_life <= 0)return;// 获取当前动画状态AnimatorStateInfo stateInfo = m_ani.GetCurrentAnimatorStateInfo(0);// 如果处于待机状态if (stateInfo.nameHash == Animator.StringToHash("Base Layer.idle") && !m_ani.IsInTransition(0)){m_ani.SetBool("idle", false);// 待机一定时间m_timer -= Time.deltaTime;if (m_timer > 0)return;// 如果距离主角小于1.5米,进入攻击动画状态if (Vector3.Distance(m_transform.position, m_player. m_transform.position) < 1.5f){m_ani.SetBool("attack", true);}else{// 重置定时器m_timer=1;// 设置寻路目标点m_agent.SetDestination(m_player. m_transform.position);// 进入跑步动画状态m_ani.SetBool("run", true);}}// 如果处于跑步状态if (stateInfo.nameHash == Animator.StringToHash("Base Layer.run") && !m_ani.IsInTransition(0)){m_ani.SetBool("run", false);// 每隔1秒重新定位主角的位置m_timer -= Time.deltaTime;if (m_timer < 0){m_agent.SetDestination(m_player. m_transform.position);m_timer = 1;}// 追向主角MoveTo();// 如果距离主角小于1.5米,向主角攻击if (Vector3.Distance(m_transform.position, m_player. m_transform.position) <= 1.5f){//停止寻路m_agent.ResetPath();// 进入攻击状态m_ani.SetBool("attack", true);}}// 如果处于攻击状态if (stateInfo.nameHash == Animator.StringToHash("Base Layer.attack") && !m_ani.IsInTransition(0)){// 面向主角RotateTo();m_ani.SetBool("attack", false);// 如果攻击动画播完,重新进入待机状态if (stateInfo.normalizedTime >= 1.0f){m_ani.SetBool("idle", true);// 重置计时器m_timer = 2;m_player.OnDamage(1);}}// 死亡if (stateInfo.nameHash == Animator.StringToHash("Base Layer.death") && !m_ani.IsInTransition(0)){if (stateInfo.normalizedTime >= 1.0f){OnDeath();}}}// 转向目标点void RotateTo(){// 当前角度 Vector3 oldangle = m_transform.eulerAngles;// 获得面向主角的角度m_transform.LookAt(m_player.m_transform);float target = m_transform.eulerAngles.y;// 转向主角float speed = m_rotSpeed * Time.deltaTime;float angle = Mathf.MoveTowardsAngle(oldangle.y, target, speed);m_transform.eulerAngles = new Vector3(0, angle, 0);}// 寻路移动void MoveTo(){float speed = m_movSpeed * Time.deltaTime;m_agent.Move(m_transform.TransformDirection((new Vector3(0, 0, speed))));}// 伤害public void OnDamage(int damage){m_life -= damage;// 如果生命为0,销毁自身if (m_life <= 0){m_ani.SetBool("death", true);}}}

我发现以书中的逻辑:僵尸每次到达攻击范围后,只会发起一次攻击,然后就转为IDEL状态,然后再检测是否有攻击,没有则继续追有则再发起攻击。

感觉运行起来的效果不是太好,因为僵尸只攻击一次(也就是挥一次手臂),然后就恢复站立状态,等下再挥,很不像僵尸的作风。至少也得连续挥舞吧。

连续挥舞有两种实现方式:

1.设置Attack的动画为Loop,然后将上述代码中的这一句if(stateInfo.normalizedTime > 1.0f),将1.0f稍微该大些,这样僵尸就会挥动很多次手臂。

但我觉得这种方式直接改掉了Attack这个动画本来的意义,不采用

2.对Animator中的Attack状态做些变化,目前Attack这个状态有下面的3个状态变化,

那么目前我就需要 一个attack -> attack的状态变化,以实现attack的连续执行。

设置如下:

这样就建立了attack->attack的动画过渡效果,然后还需要代码控制这一状态,于是再设置:

这样,当bool值attack的值为False时,Attack这个动画就不再重复了。

我改动的代码如下:

if (stateInfo.fullPathHash == Animator.StringToHash ("Base Layer.attack")&& !m_ani.IsInTransition(0)) {RotateTo ();if (m_timer > 0) {m_timer -= Time.deltaTime;return;}m_ani.SetBool ("attack", false);if (stateInfo.normalizedTime >= 1.0f) {m_ani.SetBool ("idle", true);m_timer = 0.1f;}}

这里,我将在RotateTo后面等待m_Timer的时间,这个时间也就是动画重复播放的时间,这个时间过之后,我就会设置Attack的值为False,然后当再播放完一次时,就设置idle为true,然后程序就会转而执行idle的部分了。

总体效果就是:僵尸到达攻击范围,攻击N次,然后停止,再继续攻击N次,直到主角死亡,或者不再攻击范围而追击主角。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。