动画生硬切换:animation.play();//极少使用,常用融合方法
动画融合淡入:animation.CrossFade(“Idle”, 0.2f);//0.2f为与前一动画的融合百分比为20%
枚举做状态机:
AI系统 - 寻路系统:
关键要素:
1、寻路元件
挂载寻路组件

2、寻路平面(地形)
地形设置成导航静态,进入预备役(以此为基准提取数据,可以修改删减,显示数据)

打开Navigation窗口在Bake栏下点Bake

烘焙数据:蓝色区域就是寻路平面,烘焙数据可以与显示数据分离

设置障碍物:障碍物勾选Navigation Static,重新烘焙,障碍物被添加

设置目标点,引用UnityEngine.AI,引用寻路系统

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.AI;//引用UnityEngine.AI
  5. public enum EnemySta
  6. {
  7. Move,
  8. Idle,
  9. Death
  10. }
  11. public class EnemyControl : MonoBehaviour {
  12. public Animation anim;
  13. public EnemySta enemySta;
  14. //因为我们需要经常用到目标的状态,所以把TransForm改成了PlayerControl
  15. public PlayerControl moveTarget;//设置目标点
  16. public NavMeshAgent navMeshAgent;//引用寻路系统
  17. public MonsterManager manager;//怪物属于那个管理器
  18. private int enemyHealth = ;//设置怪物生命值
  19. // Use this for initialization
  20. void Start () {
  21. enemySta = EnemySta.Move;
  22. }
  23.  
  24. // Update is called once per frame
  25. void Update () {
  26. if (Input.GetKeyDown(KeyCode.Alpha1))
  27. {
  28. enemySta = EnemySta.Move;
  29. }
  30. if (Input.GetKeyDown(KeyCode.Alpha2))
  31. {
  32. enemySta = EnemySta.Idle;
  33. }
  34. if (Input.GetKeyDown(KeyCode.Alpha3))
  35. {
  36. enemySta = EnemySta.Death;
  37. }
  38. Action();
  39. }
  40. void Action()
  41. {
  42. switch (enemySta)
  43. {
  44. case EnemySta.Move:
  45. Move();
  46. break;
  47. case EnemySta.Idle:
  48. Idle();
  49. break;
  50. case EnemySta.Death:
  51. Death();
  52. break;
  53. }
  54. }
  55. void Move()
  56. {
  57. anim.CrossFade("Move", 0.2f);
  58. navMeshAgent.SetDestination(moveTarget.transform.position);//让对应组件调用一个SetDastination(目标点)方法
  59. //如果怪物的目标死了
  60. if (moveTarget.playSta == PlaySta.Death)
  61. {
  62. //寻路停止
  63. navMeshAgent.isStopped = true;
  64. //状态切换到闲置
  65. enemySta = EnemySta.Idle;
  66. }
  67. }
  68. void Idle()
  69. {
  70. anim.CrossFade("Idle", 0.2f);
  71. }
  72. public void Damage()
  73. {
  74. //受伤减血
  75. enemyHealth -= ;
  76. //Debug.Log("怪物生命"+enemyHealth);
  77. //如果血到了0
  78. if (enemyHealth <= )
  79. {
  80. //状态变成死亡状态
  81. enemySta = EnemySta.Death;//怪物死亡:停止寻路,失效碰撞体(防止实体造成伤害)
  82. navMeshAgent.isStopped = true;
  83. gameObject.GetComponent<MeshCollider>().enabled = false;
  84. //gameObject.tag = "Untagged";
  85. }
  86. }
  87. void Death()
  88. {
  89. anim.CrossFade("Death", 0.2f);
  90. }
  91. public void DeathEvent()
  92. {
  93. //在管理器列表中移除自己
  94. manager.monsterList.Remove(this);
  95. //销毁自己
  96. Destroy(this.gameObject);
  97. }
  98. }

Max Slope:坡度设置
Step Height:高度设置,低于高度可忽略

Speed:移动速度
Angular Speed:转向速度
Acceleration:启动速度,加速度
摄像机跟随
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class CameraFollow : MonoBehaviour {
  5. public Transform target;//目标点
  6. public Vector3 distance;//目标点的距离,和目标点保持一定距离
  7. public Vector3 lookAtOffSet;//看向点与目标点的偏移量
  8. private Vector3 targetPos;
  9. // Use this for initialization
  10. void Start () {
  11. distance = transform.position - target.position;
  12. }
  13.  
  14. // Update is called once per frame
  15. void Update () {
  16.  
  17. }
  18. private void LateUpdate()
  19. {
  20. //目标点加距离 = 摄像机的目标位置
  21. targetPos = target.position + distance;
  22. //向目标位置移动,每次百分之10
  23. transform.position = Vector3.Lerp(transform.position, targetPos, 0.1F);
  24. //看向目标点
  25. transform.LookAt(target.position + lookAtOffSet);
  26. }
  27. }
lookAtOffSet:设置摄像机看向点的偏移量(点),避免人物总是在画面中央
射击功能:
核心功能(射线,碰撞,调用掉血方法)+交互功能(射线闪光特效,音效)
空物体Fire
----音效Audio
----动画
----射线
----粒子特效
--------子物体:Spotlight聚光灯,开闭,range变化

设置灯光动画

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public enum PlaySta
  5. {
  6. Move,
  7. Idle,
  8. Death
  9. }
  10. public class PlayerControl : MonoBehaviour
  11. {
  12. public Animation anim;
  13. public PlaySta playSta;
  14. // Use this for initialization
  15. void Start()
  16. {
  17. playSta = PlaySta.Move;
  18. }
  19. // Update is called once per frame
  20. void Update()
  21. {
  22. float h = Input.GetAxis("Horizontal");
  23. float v = Input.GetAxis("Vertical");
  24. moveDir.x = h;
  25. moveDir.z = v;
  26. cd += Time.deltaTime;
  27. Action();
  28. }
  29. void Action()
  30. {
  31. switch (playSta)
  32. {
  33. case PlaySta.Move:
  34. Move();
  35. Attack();
  36. Rot();
  37. break;
  38. case PlaySta.Idle:
  39. Idle();
  40. Attack();
  41. Rot();
  42. break;
  43. case PlaySta.Death:
  44. Death();
  45. break;
  46. }
  47. }
  48. Vector3 moveDir;
  49. Vector3 lookPoint;
  50. RaycastHit hit;
  51. public float moveSpeed = ;
  52. void Move()
  53. {
  54. anim.Play("Move");
  55. transform.position += moveDir * moveSpeed * Time.deltaTime;
  56. if (moveDir.magnitude < 0.01f)
  57. {
  58. playSta = PlaySta.Idle;
  59. }
  60. }
  61. //把转向功能提炼出来
  62. void Rot()
  63. {
  64. if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, , << ))
  65. {
  66. lookPoint = hit.point;
  67. lookPoint.y = transform.position.y;
  68. transform.LookAt(lookPoint);
  69. }
  70. }
  71. void Idle()
  72. {
  73. anim.Play("Idle");
  74. if (moveDir.magnitude >= 0.01f)
  75. {
  76. playSta = PlaySta.Move;
  77. }
  78. }
  79. float cd;
  80. public void Damage()
  81. {
  82. cd = ;//无敌时间,受伤间隔
  83. playSta = PlaySta.Death;
  84. }
  85. void Death()
  86. {
  87. anim.Play("Death");
  88. }
  89. //触发器判定死亡
  90. //public void OnTriggerEnter(Collider other)
  91. //{
  92. // if (other.tag == "Monster")
  93. // {
  94. // if (cd > 0.5f)
  95. // {
  96. // Damage();
  97. // }
  98. // }
  99. //}
  100. //改良版:碰撞器判定死亡
  101. public void OnCollisionEnter(Collision other)
  102. {
  103. if (other.gameObject.tag == "Monster")
  104. if (cd > 0.5f)
  105. {
  106. Damage();
  107. }
  108. }
  109. public AudioSource fireAudio;
  110. public Animation fireAnim;
  111. public Transform firePos;
  112. public LineRenderer lineRenderer;
  113. private RaycastHit fireHit;
  114. void Attack()
  115. {
  116. if (Input.GetMouseButtonDown())
  117. {
  118. fireAudio.Play();
  119. fireAnim.Stop();//Stop避免前一动画未执行完,后一动画不会执行
  120. fireAnim.Play();
  121. if (Physics.Raycast(new Ray(firePos.position,firePos.forward),out fireHit,))
  122. {
  123. //如果我打中的目标是怪物
  124. if (fireHit.collider.tag == "Monster")
  125. {
  126. //这个目标受伤
  127. fireHit.collider.GetComponent<EnemyControl>().Damage();
  128. }
  129. SetFirePos(fireHit.point);
  130.  
  131. }
  132. else
  133. {
  134. SetFirePos(firePos.transform.position + firePos.forward * );
  135. }
  136. }
  137. }
  138. void SetFirePos(Vector3 hitPos)
  139. {
  140. lineRenderer.SetPosition(, firePos.position);
  141. lineRenderer.SetPosition(, hitPos);
  142. }
  143. //还原射线到枪口位置
  144. public void ReSetFirePos()
  145. {
  146. lineRenderer.SetPosition(, firePos.position);
  147. lineRenderer.SetPosition(, firePos.position);
  148. }
  149. }

----射线

positions默认世界位置
Element 0:枪口位置
Element 1:目标点位置

Materials射线材质:LineRenderMaterial
width射线宽度:
SetPosition方法:0,1参数是element0,element1

射线关联:
枪口位置,绑定在骨骼的武器位上
如果没有,就放在正前方上0.15,0.3,0.7
重置射线:
设置在动画的第10帧,调用消失方法

新建脚本FireEvent,调用父级Player的脚本

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class FireEvent : MonoBehaviour {
  5. public PlayerControl player;
  6. // Use this for initialization
  7. void Start () {
  8.  
  9. }
  10.  
  11. // Update is called once per frame
  12. void Update () {
  13.  
  14. }
  15. public void Fire()
  16. {
  17. player.ReSetFirePos();
  18. }
  19. }

射线宽度调整:添加关键帧,调整曲线,效果先细后粗

怪物管理器;
添加空物体和脚本类,生成点

给怪物管理器添加预制体的引用
注意:对象在场景中和类在资源中的区别

怪物属于那个管理器

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. public class MonsterManager : MonoBehaviour {
  6. List<Transform> birthPoint;
  7. public GameObject monsterPreGo;
  8. public List<EnemyControl> monsterList;
  9. public int MaxMonsterCount = ;//最大怪物数
  10. public PlayerControl player;
  11. // Use this for initialization
  12. void Start () {
  13. birthPoint = new List<Transform>();
  14. monsterList = new List<EnemyControl>();
  15. for (int i = ; i < transform.childCount; i++)
  16. {
  17. birthPoint.Add(transform.GetChild(i));
  18. }
  19. }
  20.  
  21. // Update is called once per frame
  22. void Update () {
  23. }
  24. private void FixedUpdate()
  25. {
  26. CheckMonster();
  27. }
  28. void CreateMonster()
  29. {
  30. //实例化一个怪物
  31. GameObject go = Instantiate<GameObject>(monsterPreGo);
  32. //怪物的位置设置任意出生点
  33. go.transform.position = birthPoint[Random.Range(,birthPoint.Count)].position;
  34. //取得怪物脚本
  35. EnemyControl monster = go.GetComponent<EnemyControl>();
  36. //把怪物放到管理器列表里
  37. monsterList.Add(monster);
  38. //指定怪物的目标
  39. monster.moveTarget = player;
  40. //指定怪物的管理者
  41. monster.manager = this;
  42. }
  43. void CheckMonster()
  44. {
  45. if (monsterList.Count < MaxMonsterCount)
  46. {
  47. CreateMonster();
  48. }
  49. }
  50. }
角色穿墙问题:
Drag=1防止被墙弹飞,XZ轴解锁

怪物死亡:移出列表,摧毁游戏物体,放在死亡动画最后一帧调用

  1. public void DeathEvent()
  2. {
  3. //在管理器列表中移除自己
  4. manager.monsterList.Remove(this);
  5. //销毁自己
  6. Destroy(this.gameObject);
  7. }

更换场景,重新烘焙,并添加floor和碰撞体

怪物管理器添加积分系统

Unity3D学习笔记(十五):寻路系统的更多相关文章

  1. python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  2. (转载)西门子PLC学习笔记十五-(数据块及数据访问方式)

    一.数据块 数据块是在S7 CPU的存储器中定义的,用户可以定义多了数据块,但是CPU对数据块数量及数据总量是有限制的. 数据块与临时数据不同,当逻辑块执行结束或数据块关闭,数据块中的数据是会保留住的 ...

  3. (C/C++学习笔记) 十五. 构造数据类型

    十五. 构造数据类型 ● 构造数据类型概念 Structured data types 构造数据类型 结构体(structure), 联合体/共用体 (union), 枚举类型(enumeration ...

  4. MySQL学习笔记十五:优化(2)

    一.数据库性能评测关键指标 1.IOPS:每秒处理的IO请求次数,这跟磁盘硬件相关,DBA不能左右,但推荐使用SSD. 2.QPS:每秒查询次数,可以使用show status或mysqladmin ...

  5. MYSQL进阶学习笔记十五:MySQL 的账号权限赋予!(视频序号:进阶_33,34)

    知识点十六:MySQL的账号权限赋予(33) 一.MySQL权限简介 关于mysql的权限简单的理解就是mysql允许你做你全力以内的事情,不可以越界.比如只允许你执行select操作,那么你就不能执 ...

  6. python 学习笔记十五 django基础

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  7. Java基础学习笔记十五 集合、迭代器、泛型

    Collection 集合,集合是java中提供的一种容器,可以用来存储多个数据. 在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数组既然都 ...

  8. Python3学习笔记十五

    ---恢复内容开始--- 1.  jquery的属性操作  $().attr(属性名)    取值 $().attr(属性名,属性值)      赋值 <!DOCTYPE html> &l ...

  9. angular学习笔记(十五)-module里的'服务'

    本篇介绍angular中的模块:module 在笔记(二)http://www.cnblogs.com/liulangmao/p/3711047.html里已经讲到过模块,这篇主要讲模块的 '服务' ...

  10. Java学习笔记十五:Java中的成员变量和局部变量

    Java中的成员变量和局部变量 一:成员变量: 成员变量在类中定义,用来描述对象将要有什么 成员变量可以被本类的方法使用,也可以被其他类的方法使用,成员变量的作用域在整个类内部都是可见的 二:局部变量 ...

随机推荐

  1. 共享访问在.NET中的编程实现

    转载:http://blog.csdn.net/zhzuo/article/details/1732937 共享访问在.NET中的编程实现 发布日期:2007-08-08 | 更新日期:2009-03 ...

  2. SQL Server 学习博客分享列表(应用式学习 + 深入理解)

    SQL Server 学习博客分享列表(应用式学习 + 深入理解) 转自:https://blog.csdn.net/tianjing0805/article/details/75047574 SQL ...

  3. Java-mybatis-一次执行多条SQL语句

    mysql数据库 1.修改数据库连接参数加上allowMultiQueries=true,如: hikariConfig.security.jdbcUrl=jdbc:mysql://xx.xx.xx: ...

  4. ABP项目创建

    第一种:1.在MyAbp.Migrator下面的appsettings.json里面的sql连接语句 MyAbp.Web.Host 下面的appsettings.json 里面的连接语句2.把MyAb ...

  5. HTTP头部信息解释分析(详细整理)

    这篇文章为大家介绍了HTTP头部信息,中英文对比分析,还是比较全面的,若大家在使用过程中遇到不了解的,可以适当参考下 HTTP 头部解释 1. Accept:告诉WEB服务器自己接受什么介质类型,*/ ...

  6. 使用Navicat导入excel表

    1:首先创建Navicat与数据库的连接 2:,从数据库中选择要导入的表 3:导入向导,选择要导入的数据类型 4:创创建excel表:一般第一行需要与表的属性相对应,这样就不需要手动设置对应栏位 不一 ...

  7. JSP表单提交与接收

    JSP表单提交与接收 在Myeclipse中新建web project,在webroot中新建userRegist1.jsp,代码如下 <%@ page contentType="te ...

  8. Kettle定时抽取两个库中的两个表到目标库SYS_OPLOG表

     A库a表(红色为抽取字段): 关联用户表: B库b表(红色为抽取字段): 关联用户表  C目标库SYS_OPLOG表(c表) 利用kettle抽取A库a表(具体名称见上图),B库b表的上面红色框起来 ...

  9. 蒙特卡罗(Monte Carlo)方法简介

    蒙特卡罗(Monte Carlo)方法,也称为计算机随机模拟方法,是一种基于"随机数"的计算方法. 二 解决问题的基本思路 Monte Carlo方法的基本思想很早以前就被人们所发 ...

  10. Lintcode: k Sum II

    Given n unique integers, number k (1<=k<=n) and target. Find all possible k integers where the ...