对金玺曾版《Unity3D手机游戏开发》第三章“第一人称射击游戏”修改,使支持僵尸连续攻击
2015-12-24 19:18
791 查看
我个人觉得这本书写的至少很和我口味,而且他的光盘资料也很详尽,比如,一个实例,不仅有一个完整的实现工程,还有一份供作练习的工程(该工程中没有要练习的部分,而资源啥的都有),让人感觉很好。
这本书下载电子版也很方便,比如:http://download.csdn.net/detail/u012337666/8402165。
我接下来具体说说自己对 第三章“第一人称射击游戏”中的改动。
先上改动前的源代码:
我发现以书中的逻辑:僵尸每次到达攻击范围后,只会发起一次攻击,然后就转为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这个动画就不再重复了。
我改动的代码如下:
总体效果就是:僵尸到达攻击范围,攻击N次,然后停止,再继续攻击N次,直到主角死亡,或者不再攻击范围而追击主角。
这本书下载电子版也很方便,比如:http://download.csdn.net/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 initialization void 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 frame void 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次,直到主角死亡,或者不再攻击范围而追击主角。
相关文章推荐
- Unity leapmotion开发实录(5)完结篇
- Unity和Lua交互
- Unity的链接等
- unity 雷1 -- 代码动态切换material
- Unity3D规则之Unity Root Motion / Bake into Pose 的问题
- 【Unity3D】浅谈Vector3的点积与叉积
- 【术】Unity中c#的foreach产生GC的原因分析
- win10下Unity打开无反应,任务管理器中却有进程
- unity3D -OnGUI.Slider
- unity的 Social API
- Unity3d 双摇杆 easyTouch
- unity上用EasyTouch如果同时有EasyJoystick的话,不能同时按EasyJoystick和EasyTouch的解决办法
- Unity3D-UGUI-drag and drop实现拖拽放下功能
- unity3d物理赛车系统
- Unity3d向web服务器发送数据
- Unity3d中四元数的使用
- 用Unity3D想做一个简单的赛车游戏,现在的问题是转弯的时候很容易出现翻车的情况,求解决思路
- Unity3D教程:制作简单汽车游戏
- Unity3d 赛车车辆各类性能算法---总结(转)
- Unity3d移动代码(脚本)向前向后以及转弯,速度转向控制