Unity记录6.1-动作-角色移动、跳跃与受力
汇总:Unity 记录
开源地址:asd123pwj/asdGame2024/09/24:真是尴尬啊,这个月没有东西可以写,只能放点去年的存稿了。
摘要:角色的碰撞判断、持续受力与瞬时受力。
地面/墙壁接触判断-2023/09/20-2023/09/21
- 根据接触点法向量来判断接触方向,接触方向包括上下左右。
- 在
OnCollisionEnter2D
、OnCollisionStay2D
、OnCollisionExit2D
里面运行_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
- 移动现在分为两类,一类是收到持续的力的作用,一类是收到瞬时的力。
- 持续力如左右移动,有最大速度,无法超过最大速度。
- 瞬时力如跳跃。无最大速度。
- 下图为示例,前面测试左右移动和跳跃,后面测试朝鼠标移动。
- 除了左右移动和跳跃外,还顺带测试了朝鼠标移动,证明受力正常。
- 下面是代码,速度限制的代码提供了两个版本,一个原始和一个简化后的。
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);
}
}
文章目录
关闭
共有 0 条评论