unity动作游戏开发笔记

2017.7.12
一、
① 1 创建动画的人物
② 人物和人物动画分离 使用同一个骨骼

③ 2 检查人物骨骼映射的位置 手动调整

④ 3 定位手上的武器
⑤ 放到相应骨骼的子物体下面 属性清零

二、人物换装与颜色更换
1 更换Rendrer 里面的Mesh 组件

三、 NGUI的界面开发
1 导入素材
2 选中素材 制作图集 右键Open Altas

3 NGUI 操作界面

1 细节 :(为了操作清楚建议把UIRoot 的位置离Player一定距离)
调节Camera 的图标大小

2 创建Sprite 精灵 选择图集
3 手动创建一个Button
Attach 》 BoxCollider
Attach –》ButtonSCripts
PlayerSound 添加声音
添加代码注意

4 创建选择颜色按钮
1 创建容器 Color Container

依次复制创建

5 为Player 创建直射光源和点光源
6 为Player 添加自动旋转
Window–》Animation

四、处理换装系统
1 创建主类 MenuController(MainCamera上)
2 创建方法

3 颜色控制主方法
Public void OnChangeColor(Color c){
}

其他方法调用主方法
Public void OnChangeColorPurple(){
OnChangeColor(Color.Purple)
(因为紫色Purple在unity自带库中找不到,需要自己定义)
}

4 通过修改Mesh和Color来实现换装
1 创建 public Mesh[ ] headMeshArray 和 索引 private int headMeshIndex = 0;
2 public OnHeadMeshNext(){
headMeshIndex++;
headMeshIndex%=headMeshArray.length;
headRender=headMeshArray[headMeshIndex];
}
3 注册Button的点击事件

4 更换全部身体颜色
Public SkinedMeshRenderer[] bodyArray; // 定义身体的数组
Public OnChangeColor(Color c){
Forech(ShinedMeshRenderer readerer in bodyArray){
Readerer.color= c;
}
}
实践:换装组件的

五、换装信息的存储和加载

通过数组的索引来实现信息的存储和再次加载

1 颜色数组填充并且赋值索引
private int colorIndex;
Private Color[] colorArray;
colorArray=new Color[]{ Color.bule,Color.cyan…};

2 设置存储信息函数
void Save(){
PlayerPrefs.setInt(“HeadIndex”,headIndex);
PlayerPrefs.setInt(“BodyIndex”,bodyIndex);
PlayerPrefs.setInt(“ColorIndex”,ColorIndex);
}
3 SceneManager.LoadScene(1);
细节:加载下一个场景的时候不销毁 带脚本的 游戏物体
Void Start(){
DontDestoryOnLoad(this.gameobject);
}

六、创建环境
七、摄像机的跟随

1 调整摄像机的位置到主角的合适的位置 记录下差值
2 利用标签查找Player游戏物体
Public const string player = “Player”; //定义一个常量来表示”Player”(防止写错)
3 创建相机跟随的脚本FollowPlayer
Player=GameObject.FindGameObjectWithTag(Tags.player).Transform;

(在Update函数下操作)
Offset=transform.position-player.position; //获得偏移量
Vector targetPos=player.position+offset; //获得最后的位置
Transform.position= Vector3.Lerp(transform.position,targetPos,speed); //摄像机渐变移动位置
Quaternion targetRotation = Quaternion.LookRotation(player.position - transform.position); //获得最后朝向
Transform.rotation = Quaternion.Slerp(transform.position,targetRotation,speed);

八、使用CharacterController控制人物移动

1 添加CharacterController组件 修改属性
2 创建PlayerMove脚本 获得CharacterController 组件
CharacterController cc= getCompentent();
在Update()下
Float h= input.GetAxis(“Horizontal”);
Float v=input.getAxis(“Vertical”);
If(Mathf.Abs(h)>0.1||Mathf.Abs(v)>0.1){
Vector3 dir =new Vctor3(h,0,v); //获得按键的方向
transform.lookAt(dir+transform.position); //更新朝向
cc.SimpleMove(transform.forword*speed); //添加速度
}

九、添加虚拟按钮

1 创建虚拟按钮的UI 设置定位

2 给虚拟杆添加 boxcollider Button属性
3 虚拟干添加Joystick 脚本
Void OnPress(bool isPress){
this.isPress= isPress;
}
4 处理逻辑
1 输出UICamera.lastTouchPosition的位置
2 控制杆的原点位置与上面的位置建立联系
3 获得控制杆的transform来赋值
4 触摸抬起之后的逻辑处理
5 控制杆的移动范围限制在背景之内
//NGUI自带判断是否触摸的函数
Void OnPress(bool isPress){
this.isPress=isPress;
If(isPress==false){
//鼠标离开时摇杆归位
joystick.LocalPostion=vector3.zero;
h=0; v=0; ////位移变量归零
}
}

(在UPdate函数下)
Vector2 touchPos=UICamera.lastTochPosition;
touchPos - = new Vector2(91,91); //以摇杆的中心为原点
If(touch>60){
//限定摇杆的最大移动范围是60
touchPos=touchPos.normalized*60
}
Else{
joystick.localPosition=tocuhPos;
}

//获得Player的位移变量
h=touchPos.x/60 //在x轴的位移变量
v=touchPos.x/60 //在y轴的位移变量

十、状态机的设置

1 调整人物动画的骨骼,是否映射正确
2 勾选Back Into Pose (若是循环播放勾选looptime loopPose)
3 按情况分类
1 攻击 和 非攻击
2 首先考虑默认状态 PlayerStand
PlayerRun bool
Attack Trigger
注意:只有当前播放动画为PlayerRun时,才可以控制主角移动
PlayerRun和PlayerStand动画使用Bool 触发器(不会立刻反弹)

十一、攻击的动画控制

1 创建监听函数 Public void OnNormalAttack() …
2 查找攻击按钮,添加监听事件
注意:当重复使用查找到的游戏物体时,应该创建一个引用
EventDelegate RedAttack = new EventDelegate(this, “OnRedAttack”);
GameObject redAttack = GameObject.Find(“RedAttack”);
//引用变量 提高效率
redAttack.GetComponent().onClick.Add(RedAttack);
redAttack.SetActive(false);
3 创建连招
1 创建可连招区间

2 创建代码监听
public void AttackBEvent1()
{
isAttackB = true; //播放AtackA并且到达此区间,生成播放AttackB的条件
}
public void AttackBEvent2()
{
isAttackB = false;
}
3 触发连招
public void OnNormalAttack()
{
if(isAttackB&&playerAnim.GetCurrentAnimatorStateInfo(0).IsName(“AttackA”))
{
playerAnim.SetTrigger(“AttackB”); //触发连招
}
else
{
playerAnim.SetTrigger(“AttackA”);
}
}
注意:在触发连招时,必须把Attack的HasExitTime勾选

十一、Boss 状态的设置
1 Boss骨骼的映射
2 更新其他动画信息

3 完善Boss 的其他信息

4 死亡动画的特殊处理

十二、Boss的AI

1 获得Player的实时位置
2 设置最短攻击距离
3 细节处理
1 设置Boss 的攻击频率
2 每次触碰Player 立刻攻击
3 Boss攻击完毕才可以触发Run动画
模型导入的一般处理方式:
1 调整Rig 模式

2 检查模型各个部位的映射情况
3 调整动画的属性

4 动画状态机的设置
重复播放动画
不重复播放动画
任何情况下的播放动画
5 逻辑处理
1 攻击距离之内 设置计时器来改变攻击频率
2 攻击距离之外 设置Run动画并且改变位移

十三、敌人的生成
1 创建敌人生成的位置
2敌人的生成 EnemySpawn
Public GameObject Spawn(){ //拿到生成Moster的引用
Return GameObject.Instantiate(prefab, transform.position,transform.rotation)
}
3 使用携程控制敌人的生成
4 使用List集合来存储敌人
List enemyList =new List();
Public EnemySpawn mosterSpawnArray; //存储Moster的Spawn方法
Public EnemySpawn bossSpawnArray; //存储Boss的Spawn方法

//利用协程来控制敌人按时间来生成
IEnumerator Spawn(){
Forench(EnemySpawn e in mosterSpawnArray){
eneryList.add(e.Spawn()); //生成的Moster存储到怪物的集合中
}
//当第一波敌人的存在时,第二波等待生成
While(eneryList.Count>0){
Yield return new WaitForSeconds(0.2f)
}
}

十四、设置公有接口的伤害

public class ATKandDamage : MonoBehaviour {

public float hp = 100;
public float normalAttack = 50;
public float attackDistance = 1;

private Animator anim;

void Awake()
{
    anim = this.GetComponent<Animator>();
}

public virtual void TakeDanmage(float danage)
{
    if (hp > 0)
    {
        hp -= danage;
    }

    if(hp>0)
    {
        anim.SetTrigger("Damage");
    }
    else
    {
        anim.SetBool("Death", true);
    }
}

}

1 添加打击特效(通过标签触发不同特效)
2 特效定时销毁
//如果攻击到Moster,播放对应特效
GameObject.Instantiate(Resources.Load(“HitMonster”), transform.position, transform.rotation);

十五、武器攻击的处理
1 继承ATKandDamage()方法 重写其属性
2 处理动画状态机的Event事件
3 单利模式(比较容易取到List集合)
Public static SpawnManager _instance;
Void Awake(){
_instance=this;
}
4 攻击离Player距离最短的Moster
Public void AttackA(){
GameObject go=null;//存储最短攻击目标
Float diatance =attackDistance;
//只生成一个SpawnManager
Foreach(GameObject go in SpawnManager._instance.eremyList){
Vector3 temp=Vector3.Disance(this,go.transform.position);
If(temp

猜你喜欢

转载自blog.csdn.net/gsm958708323/article/details/76260689