Unity-GUI-实现角色移动与跳跃

–整理0404

1.安装环境:

Visual Studio2013
Unity5.6.1f1

实现角色移动与跳跃

**

一、准备工作:

**
(1)创建一个场景S003:在Hierarchy面板中写入LocalManager文件,写入ResourcesManager与CanvasManager.分别挂上LoadRes脚本与CanvasManagerEX脚本。(此步之前笔记讲过,用来管理资源与Canvas)
(2)加入所用资源:Image->Resources->图片003
(3)创建人物Player:在Canvas下创建,UI->Image。将图片资源拖入后,创建预制体Player。(将Canvas下的Player拖入PreFab的Resources中)
Unity-GUI-实现角色移动与跳跃_第1张图片
Unity-GUI-实现角色移动与跳跃_第2张图片

二、.编写控制人物移动的脚本:MoveControl.C#

通过调整Transform组件的属性实现游戏对象的移动。以下是需要了解的几个函数与结构体。
(1)Translate函数
Translate函数用于处理游戏对象移动。
this.Translate(移动方向 * 速度 * 前进/后退方向 * Time.deltaTime, 基准坐标系);
1)Time.deltaTime表示前一帧到当前帧或非的时间,
2)使用Transform组件 ,游戏对象移动的逻辑必须乘以deltaTime,使游戏对象的移动速度不受帧率的影响,而根据某个固定的速度移动。
3)乘以Time.deltaTime,游戏对象将以每秒1各单位的速度前进)
4)将向量单位乘以速度(speed),表示按照speed变量指定的速度移动。

(2)Vector3(x, y, z)是unity提供的用于保存三维坐标值和向量数据的结构体。
(3)键盘的输入:GetKey(用户长按按键有效),GetKeyDown(用户按下按键时有效),GetKeyUp(用户抬起按键时有效)三个方法分别获取用户键盘按键的输入

以下是控制移动的代码。

if (Input.GetKeyDown(KeyCode.Space))
        {
            frameTime = 0;
            isJump = true;

        }
        else if (Input.GetKey(KeyCode.S))
        {
            print("move s");
            this.transform.Translate(Vector3.back * Time.deltaTime * speed);
        }
        else if (Input.GetKey(KeyCode.A))
        {
            print("move a");
            this.transform.Translate(Vector3.left * Time.deltaTime * speed);
        }
        else if (Input.GetKey(KeyCode.D))
        {
            print("move d");
            this.transform.Translate(Vector3.right * Time.deltaTime * speed);
        }

其中,控制角色跳跃,需要利用弹道/抛物线s=ut+1/2at²。当按下空格键时,角色跳跃呈开口向下的抛物线,至最高点后下落,返回至地面。在跳跃过程中,设生命线为frameTime。设抛物线的两个零点是0与0.6,也就是跳跃过程的生命线应小于0.6。在跳跃过程中,角色y值发生改变。由函数getY()得到y的变化值与返回布尔类型的isEnd。

   float a = 18.5f;
   float h = 6.66f;
   bool isJump = false;
   public float getY(float t, out bool isEnd)
   {
       if (t < 0.6)
       {
           isEnd = false;
       }
       else
       {
           isEnd = true;
       }


       if (t > 0.6)
       {
           return 0;
       }

       //带入两个零点解方程,计算出a,h的值
       float y = 0.45f - 5 * (t - 0.3f) * (t - 0.3f);

       return y;

   }

在Start()中定义isJump 判断是否跳跃,并存贮初始y值。

        isJump = false;
        initposy = this.transform.position.y;
        //将初始y值存储起来

在定义跳跃的代码中,初始frameTime = 0; isJump = true;
当 isJump = true;开始跳跃过程,实时时间frameTime+= Time.deltaTime;当frameTime>0.6,生命线结束,isEnd=true;
当getY()返回isEnd为true时,表示frameTime>0.6,跳跃过程结束。

        if (isJump == true)
        {
            frameTime += Time.deltaTime;
            //生命线frameTime
            if (frameTime > 0.6f)
            {
                isEnd = true;

            }
            float y = getY(frameTime, out isEnd);
            this.transform.position = (new Vector3(this.transform.position.x, y * 100 + initposy, this.transform.position.z));

            if (isEnd == true)
            {

                isJump = false;
            }

            Debug.Log(y);
        }

定义子弹发射,当按下k键时,发射子弹。其实就是按下k键,生成一个GameObject子弹对象。并定义生成后的位置。
此处,通过字典查找资源boom。

  if (Input.GetKeyDown(KeyCode.K))
        {
            Debug.Log("按下了K");

            GameObject g = GameObject.Instantiate(LoadRes.getPrefab(ResName.boom
                 ), CanvasManagerEX.canvas1.transform);
            //生成后重新定义位置
            g.GetComponent().localPosition = this.GetComponent().localPosition;


        }

定义预制体字典prefabDic:
1.生成字典prefabDic

 //****1.生成字典prefabDic****

    static Dictionary<string, GameObject> prefabDic = new Dictionary<string, GameObject>();
    //****2.生成字典资源spDic****
    static Dictionary<string, Sprite> spDic = new Dictionary<string, Sprite>();

2.对字典prefabDic进行封装

    //在另一个脚本里面 定义资源字符串ResName,调用时用ResName.boom
    //*****对字典进行封装******

    // PrefaDic字典返回
    public static GameObject getPrefab(string key)
    {
        return prefabDic[key];  
    }

    // PrefaDic字典add
    public void save2PrefaDic(string key, GameObject value)
    {

        if (prefabDic.ContainsKey(key) == true)
        {
            return;
        }

        prefabDic.Add(key, value);


    }

3.添加键入PrefaDic字典

  void Awake()
    {
        Debug.Log("w");
        //PrefaDic字典add过程
        save2PrefaDic(ResName.boom, Resources.Load<GameObject>(ResName.boom));
        save2PrefaDic(ResName.Magic0, Resources.Load<GameObject>(ResName.Magic0));
        save2PrefaDic(ResName.Magic1, Resources.Load<GameObject>(ResName.Magic1));
        save2PrefaDic(ResName.Magic2, Resources.Load<GameObject>(ResName.Magic2));
        save2PrefaDic(ResName.Magic3, Resources.Load<GameObject>(ResName.Magic3));
        save2PrefaDic(ResName.Magic4, Resources.Load<GameObject>(ResName.Magic4));
       
        instance = this;

    }

三、发射子弹fps序列帧
1.找到几张子弹爆炸的动画图片,添加到PrefaDic字典。在spDic字典中加入存放爆炸图片的列表list进行调用。

 // 定义资源字符串ResName,调用时用ResName.boom
    //List类型的  getSp()

    public static List<Sprite> getSp(List<string> key)
    {
        List<Sprite> list = new List<Sprite>();
        foreach (string _key in key)
        {
            list.Add(getSp(_key));
        }
        return list;
     


    }
    //spDic字典(面向对象) 封装getSp,返回键值
    public static Sprite getSp(string key)
    {
        //key不存在时不报错
        if (spDic.ContainsKey(key) == true)
        {
            return spDic[key];

        }
        else
        {

            return null;  
        }


    }
 void Awake()
 {
     Debug.Log("w");
     //PrefaDic字典add过程,add 爆炸图片
     save2PrefaDic(ResName.Magic0, Resources.Load<GameObject>(ResName.Magic0));
     save2PrefaDic(ResName.Magic1, Resources.Load<GameObject>(ResName.Magic1));
     save2PrefaDic(ResName.Magic2, Resources.Load<GameObject>(ResName.Magic2));
     save2PrefaDic(ResName.Magic3, Resources.Load<GameObject>(ResName.Magic3));
     save2PrefaDic(ResName.Magic4, Resources.Load<GameObject>(ResName.Magic4));
    
     instance = this;

     //spDic字典add过程
     spDic.Add(ResName.Magic0, Resources.Load<Sprite>(ResName.Magic0));
     spDic.Add(ResName.Magic1, Resources.Load<Sprite>(ResName.Magic1));
     spDic.Add(ResName.Magic2, Resources.Load<Sprite>(ResName.Magic2));
     spDic.Add(ResName.Magic3, Resources.Load<Sprite>(ResName.Magic3));
     spDic.Add(ResName.Magic4, Resources.Load<Sprite>(ResName.Magic4));

     //存入list
     ResName.list.Add(ResName.Magic0);
     ResName.list.Add(ResName.Magic1);
     ResName.list.Add(ResName.Magic2);
     ResName.list.Add(ResName.Magic3);
     ResName.list.Add(ResName.Magic4);
  
 }

2.定义爆炸的基类BoomBase。在之后的脚本中,只需要继承这个基类,重写函数即可。
对于每一个boom动画,首先得到图片。以及播放的速度speed。
之后,定义函数changeImage(爆炸图片list列表,图片切换时间,技能结束时间)

public abstract class BoomBase : MonoBehaviour {




private Image img;
private float timeFrequency;
private List dataList = new List();
private float frameTime = 0;
private int index;
private float skillEnd;
private float bornTime;
private float speed;
 public virtual void Awake()
 {
     //对于每一个boom动画,首先得到图片
     img = this.GetComponent();
     speed = 300;
 }
 public virtual void Start()
 { 
     
 }
 //0,1,2
 //changeImage(爆炸图片list列表,图片切换时间,技能结束时间)
 public void changeImage(List _data, float _time, float _skillEnd)
 {

     timeFrequency = _time;
     dataList = _data;
     this.skillEnd = _skillEnd;
 }
 public void setImage()
 {


     if (bornTime > skillEnd)//判断1:bornTime存货死亡的时间线   进度是否结束
     {
         if (index >= dataList.Count) // 下标大于链表长度,动图资源到头,结束
         {
             return;
         }

         frameTime = 0; // frameTime 每进行一帧 0.1 就设置为0,使得每一帧播放一张图片。
         img.sprite = this.dataList[index];//得到每一帧的资源

         index++;
     }
   

    
     
    
 }
 public void Update()
 {
     //bornTime存货死亡的时间线,frameTime是每一帧时间。timeFrequency是图片切换时间
     bornTime += Time.deltaTime;
     frameTime += Time.deltaTime;

     if (frameTime > timeFrequency)//判断1:当前时间大于图片切换时间,开始获取资源
     {
         setImage();
     }

     if (bornTime < skillEnd)//判断2:bornTime存货死亡的时间线   是否正在进行
     {
         this.gameObject.GetComponent().localPosition += new Vector3(1, 0, 0) * Time.deltaTime * speed;
     }
     if (bornTime > (timeFrequency * dataList.Count + skillEnd))//判断2:技能结束,销毁gameObject
     {
         Destroy(this.gameObject);
     
     }
    

 }





}
public class ShotScript : BoomBase {



 //重载基类的Start()
 public override void Start()
 {
     base.Start();

     //需要重写调用基类的函数时,写上   base.Start();
     changeImage(LoadRes.getSp(ResName.list),0.1f,1f);
 }


 
}

你可能感兴趣的:(Unity学习笔记,Unity-GUI)