Unity记录6.1-动作-角色移动、跳跃与受力

汇总:Unity 记录
开源地址:asd123pwj/asdGame

2024/09/24:真是尴尬啊,这个月没有东西可以写,只能放点去年的存稿了。

摘要:角色的碰撞判断、持续受力与瞬时受力。

地面/墙壁接触判断-2023/09/20-2023/09/21

  • 根据接触点法向量来判断接触方向,接触方向包括上下左右。
    • OnCollisionEnter2DOnCollisionStay2DOnCollisionExit2D里面运行_on_collision
  • 但有缺陷,它的接触点太不准确了,明明两个物体间有多个碰撞点都都做了,却不准确。
    • 例如我在墙角,地面一个,墙壁一个,但是只能检测到其中一个。
public void _update_contact_count(){
    _contact_count_up = _contact_count_down = _contact_count_left = _contact_count_right = 0;
    foreach(KeyValuePair<Collision2D, int[]> kvp in _contact_count){
        _contact_count_up += kvp.Value[0];
        _contact_count_down += kvp.Value[1];
        _contact_count_left += kvp.Value[2];
        _contact_count_right += kvp.Value[3];
    }
}

public void _on_collision(Collision2D collision, string status){
    int[] udlr_count = new int[4];
    foreach (ContactPoint2D contact in collision.contacts){
        Vector2 normal = contact.normal;
        if (Mathf.Abs(normal.y) > Mathf.Abs(normal.x)){
            if (normal.y < 0) udlr_count[0] += 1;
            else udlr_count[1] += 1;
        } else {
            if (normal.x < 0) udlr_count[3] += 1;
            else udlr_count[2] += 1;
        }
    }
    if (status == "enter") _contact_count.Add(collision, udlr_count);
    else if (status == "exit") _contact_count.Remove(collision);
}

移动-2023/09/23-2023/09/26

  • 移动现在分为两类,一类是收到持续的力的作用,一类是收到瞬时的力。
    • 持续力如左右移动,有最大速度,无法超过最大速度。
    • 瞬时力如跳跃。无最大速度。
  • 下图为示例,前面测试左右移动和跳跃,后面测试朝鼠标移动。
    • 除了左右移动和跳跃外,还顺带测试了朝鼠标移动,证明受力正常。

Unity_024_playerMove.gif

  • 下面是代码,速度限制的代码提供了两个版本,一个原始和一个简化后的。
    public void _move(Vector2 direction, float force, bool isInstant=false){
        Vector2 force_speed = direction * force;
        if (!isInstant) { // such as player move
            Vector2 final_speed = new(){
                x = _restrict_value_by_ori_max_change(_actual_speed.x, _config._max_move_speed.x, force_speed.x),
                y = _restrict_value_by_ori_max_change(_actual_speed.y, _config._max_move_speed.y, force_speed.y)
            };
            _config._rb.velocity = final_speed;
        } else {// such as player jump or be blown up
            _config._rb.AddForce(force_speed, ForceMode2D.Impulse);
        }
    }

// 速度限制的简化前
float _restrict_value_by_ori_max_change(float v_ori, float v_max, float v_new){
    if (Mathf.Abs(v_ori + v_new) <= v_max) return v_ori + v_new;
    else if (v_ori >= 0){
        if (v_ori > v_max) {
            if (v_new >= 0) return v_ori;
            else return v_ori + v_new / 10;
        }
        else return v_max;
    }
    else{
        if (v_ori < -v_max){
            if (v_new < 0) return v_ori;
            else return v_ori + v_new / 10;
        }
        else return -v_max;
    }
}

// 速度限制的简化版
float _restrict_value_by_ori_max_change(float v_ori, float v_max, float v_ch){
    if (Mathf.Abs(v_ori + v_ch) <= v_max) return v_ori + v_ch;
    int dir_ori = v_ori > 0 ? 1 : -1;
    if (v_ori * dir_ori > v_max) return (v_ch * dir_ori >= 0) ? v_ori : v_ori + v_ch / 10;
    else return dir_ori * v_max;
}
  • 按键代码如下,还能简化,但暂时不搞。
public void _down_fire1(Vector2 mouse_pos){
    Vector2 rb2mouse = mouse_pos - _config._rb.position;
    _move._move(rb2mouse.normalized, _config._magnitude_move_speed.y, true);
}

public void _horizontal(float horizontal){
    Vector2 velocity = new (horizontal, 0);
    _move._move(velocity.normalized, velocity.magnitude * _config._magnitude_move_speed.x);
}

public void _vertical(float vertical){
    if (_status_contact._contact_count_down > 0){
        Vector2 velocity = new (0, vertical);
        _move._move(velocity.normalized, _config._magnitude_move_speed.y, true);
    }
}

版权声明:
作者:MWHLS
链接:https://mwhls.top/4918.html
来源:无镣之涯
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录