您的位置:首页 > 移动开发 > Unity3D

unity动作游戏开发笔记

2017-07-28 15:16 337 查看
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 单利模式
a201
(比较容易取到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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息