Unity初学4——帧动画以及主角攻击(2d)

该文来自学习chutianbo老师的笔记,链接b站

关于帧动画的制作

关于一个角色的动画制作,我们要先为这个角色加上一个组件Animator(动画控制器).在这里插入图片描述
之后在我们使用ctrl+6打开Animation面板,选中我们Prefabs下的角色,点击创建Animation Cilp,将新建文件动画放置我们在assets下创建的Animation文件夹中。
之后我们在Characters文件夹中找到不同形态的素材
在这里插入图片描述如上图,robot动作分为idle,fixed,walk三个状态,其中walk中的动画分为四个方向。我们使用Shift按住选中其中归属down的四张照片拖入Animation面板中进行帧制作即可。

问题:
1.动作只有左没有右
在这里插入图片描述
使用Filp X进行反转即可
2.名字右边三个符号分别表示调到指定帧,加入关键帧,加入事件
3.制作的帧动画事件尽量不要低于0.10,不然后面混合树的tigger判定会出bug

使用混合树为角色加上动画

在制作完动画之后,我们就需要为角色加上行为流程。
在制作animation时,他会自动创建一个对应的animator点击进入
会发现我们之前做的每个动画都散落在其中,所以按照归类,我们使用右键创建create state➡New Blend tree。
因为机器人的动画有朝向问题,所以我们在左边的paramemters中加入参数判定 Move X,和Move Y,都是float类型
在这里插入图片描述
大概做完就是这个样子
这里要记得
在这里插入图片描述
将混合树类型改为两个控制参数,然后加入自己做的动画即可
这里上述的动画我是没有做参数控制的,下述主角动画
在这里插入图片描述
分别为四个状态 idle(站立),launch(射击),Moving(奔跑),hit(受击)
Speed>0.1时 idle➡Moving
Look X和Look Y来表示面向(下面会有代码计算当前面向)
Lanuch和Hit为tigger类型当条件触发进入,且回自动跳回上一状态;

//我的角色初始面向向下
 Vector2 lookDirection = new Vector2(0, -1);
    Vector2 move;
    void Update(){
 move = new Vector2(horizontal, vertical);
        //浮点数近似相等
        if (!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
        {
            lookDirection.Set(move.x, move.y);
            //使数值归一为向量
            lookDirection.Normalize();
        }
        animator.SetFloat("Look X", lookDirection.x);
        animator.SetFloat("Look Y", lookDirection.y);
        animator.SetFloat("Speed", move.magnitude);
        }

做好了动画,使用参数控制动画

声明动画对象
Animator animator;
2.在start中获得动画实例
animator = GetComponent();
3.在FixedUpdate中加入判定

  if (vertical)
        {
            position.y = position.y + speed * Time.deltaTime*direction;
            animator.SetFloat("Move X",0);
            animator.SetFloat("Move Y", direction);
        }
        else
        {
            position.x = position.x + speed * Time.deltaTime * direction;
            animator.SetFloat("Move X", direction);
            animator.SetFloat("Move Y", 0);
        }
        rigidbodyroot.MovePosition(position);
        ```
# 关于主角攻击
动画制作同上不再赘述,这里我们讲述一下关于主角射击发出子弹的事情
1.在子弹预制件中加入刚体和碰撞体,同时为子弹projecttile预制件挂上脚本
 ``
   Rigidbody2D rigidbodyproject;
    // Start is called before the first frame update
    void start()
    {
        rigidbodyproject = GetComponent<Rigidbody2D>();
    }
    public void launch(Vector2 direction,float force){
    //给子弹一个发射的力
        rigidbodyproject.AddForce(direction*force);
        }
   private void OnCollisionEnter2D(Collision2D collision)
    {
        Debug.Log($"碰到了{collision.gameObject}");
        //子弹撞见实体时消失
        Destroy(gameObject);
        //当子弹遇见机器人时,修复机器人
        EnemyController2 emenyController2 = collision.collider.GetComponent<EnemyController2>();
        if (emenyController2 != null)
        {
            emenyController2.Fix();
        }
    }
    private void Update()
    {
        //如果没有碰到任何碰撞体,过远自动销毁
        if (transform.position.magnitude>100)
        {
            Destroy(gameObject);
        }
    }

2在主角代码中加入
public GameObject projecttilePrefabs;//表示获取子弹预制件
3.为主角加入发射函数

   void Launch()
    {
        //在指定位置创建对象
        GameObject projecttileObject = Instantiate(projecttilePrefabs, rigidbody2dRuby.position + Vector2.up * 0.5f, Quaternion.identity);
        projecttile projecttile = projecttileObject.GetComponent<projecttile>();
        projecttile.launch(lookDirection, 300);
    }

上述Instantiate表示创建实体是unity的一个api参数第一个是对象,第二个是创建位置,第三个是旋转
,Quaternion.identity表示不旋转(这里我们可以回到最开始创建主角移动时,如果不勾选冰冻z轴的样子)
4.遇见bug 233
我们会发现第一件事,unity会报错表示子弹预制件的刚体获取为null,这是因为,下述为unity官方解释:
这是因为在你创建对象时 Unity 不会运行 Start,而是在下一帧才开始运行。因此,在飞弹上调用 Launch 时,只实例化 (Instantiate),不调用 Start,因此 Rigidbody2d 仍然为空。要解决此问题,请将 Projectile 脚本中的 void Start() 函数重命名为 void Awake()。
与 Start 刚好相反,在创建对象时(调用 Instantiate 时)就会立即调用 Awake,因此在调用 Launch 之前已正确初始化 Rigidbody2d。
关于这个问题深入可以去看看MonoBehavior的生命周期
5.修完这个bug,那么我们会继续遇到bug
我们发现飞弹创建了,但是瞬间遇到主角消失了,所以这里我们需要用到图层,将主角和预制件飞弹放在不同的图层,同时在 Edit➡Project Setting➡physical 2D中取消这两个图层的勾选(即为不碰撞)

这片文章所使用的素材来自unity商店Ruby’s adventure
链接unity官网

猜你喜欢

转载自blog.csdn.net/jijikok/article/details/125949879
今日推荐