Monthly Archives: 四月 2021

Hello World

Untiy笔记–鼠标跟随移动

这里的使用场景是飞机的移动,飞机跟随鼠标移动,但飞机会有移动速度上限.
实际使用时,最大速度bigSpeed的数值可以通过unity开发工具设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    public float bigSpeed; //每毫秒最大的移动距离
    private Transform fighterTransform; //游戏对象
    private long lastUpdate; //记录最近一次update的时间
 
    private void Update(){
        //因为仅需要每次移动时刷新位置,所以不需要放在FixedUpdate里
        FollowMouseMove();
    }
 
    private void FollowMouseMove(){
        long now = (System.DateTime.Now.Ticks - 621355968000000000)/10000;
        //首先获取飞机当前位置
        Vector3 fightPos = fighterTransform.position;
        //鼠标当前位置,ScreenToWorldPoint用于转化为游戏内坐标体系
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        //2D游戏,抛去z轴信息
        mousePos = new Vector3(mousePos.x, mousePos.y, 0f);
        //飞机鼠标位置的距离
        float distance = Vector3.Distance(fightPos-fix, mousePos);
        //两帧之间最大移动距离,bigSpeed是每毫秒的最大移动距离 Update的调用时间并不准确,为了速度均衡,这里根据时间差值来计算
        float maxLen = ((float)(now - lastUpdate))*bigSpeed;
        Vector3 targetPos; //飞机的目标位置
        //飞机向鼠标位置移动  未超过最大距离
        if(distance <= maxLen){
            targetPos = mousePos;
        }else{
            //三角计算
            float dx = (maxLen*(mousePos.x-fightPos.x))/distance;
            float dy = (maxLen*(mousePos.y-fightPos.y))/distance;
            Vector3 dpos = new Vector3(dx, dy, 0f);
            targetPos = fighterTransform.position + dpos;
        }
        //TODO:targetPos是否超出屏幕范围的判断
        fighterTransform.position = targetPos; //将目标位置复制的游戏对象
        lastUpdate = now;
    }

充分使用Vector3自带运算,对计算过程做精简

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    private void FollowMouseMove(){
        long now = (System.DateTime.Now.Ticks - 621355968000000000)/10000;
        Vector3 fightPos = fighterTransform.position;
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);  //WorldToScreenPoint
        mousePos = new Vector3(mousePos.x, mousePos.y, 0f);
        float distance = Vector3.Distance(fightPos, mousePos); //当前距离
        float rank;
        float maxLen = ((float)(now - lastUpdate))*bigSpeed; //实际可以移动的最大距离
        if(distance < maxLen){
            rank = 1;
        }else{
            rank = maxLen/distance;
        }
        Vector3 dpos = (mousePos - fightPos)*rank;
        Vector3 targetPos = fighterTransform.position + dpos;
        //CanNotOUtCamera 出界判断模块
        targetPos = CanNotOUtCamera(targetPos, fighterTransform.localScale);
        fighterTransform.position = targetPos;
        lastUpdate = now;
    }
Hello World

Unity笔记–利用预制体动态创建对象

使用Unity制作射击游戏,屏幕内的每一个子弹都需要一个游戏对象,如果是单发武器还好,项目里复制几个对象,然后下面的代码就能不断循环使用。

1
2
    transform.SetAsLastSibling();
    bulletsTransform = transform.GetChild(0);

但如果需要使用连发武器,比如加特林之类的,同一时间屏幕上可能会出现许多的子弹。如果还是事先复制一堆子弹对象,就显得特别low,这里就需要动态创建子弹对象了。
首先,新建预制体子弹对象“Bullet1”,然后将其拖入Assets/Resources目录内(只有名为“Resources”目录内的资源才能动态加载)。
然后就可以在代码内创建、使用预制体对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
    //代码片段1,加载预制体, 创建对象
    GameObject bullet = Resources.Load("Bullet1") as GameObject; //加载预制体
    bullet = Instantiate(bullet); //使用这种方式加载预制体,必须序列化后才能使用
    bullet.transform.parent = cannonsTransform; //设置父级对象
    bullet.transform.localScale = bulltScale; //设置大小。。。预制体似乎为包含拖到修改大小的信息,这里使用中一个Vector3对象重新设置其大小
    bullet.transform.position = beginPos; //使用一个Vector3对象,设置初始位置
    runingBullets.Add(bullet.transform); //加入到队列
 
    //代码片段2,销毁预制体
    if(...){
        Destroy(runingBullets[i].gameObject); //销毁对象
        runingBullets.RemoveAt(i); //移出队列
    }

再unity中,创建对象是很耗资源的操作,正式项目建议创建后不要轻易销毁,而是通过SetActive(false/true)循环使用。
——-
原创内容,转载请注明出处:http://www.jiangkl.com/2021/04/unity_new_prefabs