有没有更好的方法来编写此自上而下的汽车mdoel

时间:2019-05-22 18:52:50

标签: unity3d game-physics game-development topdown

我正在写一个自上而下的汽车漂移游戏,我想让汽车绕一圈移动,并且用户通过转向来控制圆的半径,基本上,直线转向是一条直线,向左转是一个小圆圈紧随其后的汽车左侧。随着汽车转弯(两侧),我尝试使汽车转弯越来越向中心倾斜,好像它在漂移一样。

我使用统一,这是我虽然应该设计模型的方式。

  1. 这是针对手机游戏的。所以我写了一辆汽车的转向控制器,以控制它的左右,速度是恒定的。

  2. 有两个刚体。

car_fig_0

  1. 前面的白色框和灰色的大框都是刚体。用铰链连接。

  2. 每帧的前盒在其自己的z轴上旋转一定程度,并向前移动一点。因此遵循圆形。旋转多少取决于我的转向。

  3. 我可以使两个物体运动,并确保它们遵循圆形并以这种方式移动,但是我还希望在碰撞过程中具有适当的行为,在最终计划中,可能存在各种各样的碰撞。因此,我使用加力方法使它们运动并增加了速度。就其本身而言,前箱是完美的,当我改变方向盘时,它会旋转一圈,圆圈变大了,一切都很好,但是当我添加其他底盘箱时,所有的力都被弄乱了。离心力,而惯性使一切混乱。

  4. 基本上,我需要让汽车漂移的是完美的圆,用户应该能够控制圆的半径。对此建模的最佳方法是什么。

这是两个刚体的代码。

  1. 前箱代码。这只是固定的更新方法。请忽略控件相关的代码。没必要,所以我省略了。

    {
    //-------------------------
    // I N I T.
    //-------------------------
    
    current_steering_angle = controls_i.ToSignedRotation(controls_i.getSteeringAngle());
    current_steering_angle = (current_steering_angle < 0) ? (current_steering_angle + 90): current_steering_angle;
    current_steering_angle -= 45;
    
    //-------------------------
    // S P E E D.
    //-------------------------
    
    current_speed = Utils.curve_map_linear(0, 45, min_speed, max_speed, Mathf.Abs(current_steering_angle), -1);
    _rigid_body.AddRelativeForce(acceleration * Vector3.up);
    velocity = transform.InverseTransformVector(_rigid_body.velocity);
    if(velocity.y > current_speed){
        velocity.y = current_speed;
    }
    // to prevent reverse movement due to centrifugal force.
    velocity.x = 0;
    
    //-------------------------
    // R O T A T I O N.
    //-------------------------
    
    current_radius = Mathf.Sign(current_steering_angle) * Utils.exp_range_3(0, 45, min_radius, max_radius, Mathf.Abs(current_steering_angle), steering_tension, -1);
    current_rot_rate = (velocity.y / (2 * Mathf.PI * current_radius)) * 360;
    Vector3 angle = transform.localEulerAngles;
    angle.z += (current_rot_rate * Time.fixedDeltaTime);
    transform.localEulerAngles = angle;
    
    //-------------------------
    // A P P L Y.
    //-------------------------
    _rigid_body.velocity = transform.TransformVector(velocity); 
    
    }
    

Utils.exp_linear和exp_range函数只是具有一定张力的范围映射器的范围,以控制控件上转向的灵敏度。

  1. 机箱代码。

    {
    
    //-------------------------
    // I N I T.
    //-------------------------
    
    current_steering_angle = controls_i.ToSignedRotation(controls_i.getSteeringAngle());
    current_steering_angle = (current_steering_angle < 0) ? (current_steering_angle + 90): current_steering_angle;
    current_steering_angle = current_steering_angle - 45;
    current_steering_angle = ((float)((int)(current_steering_angle * Mathf.Pow(10, 5))))/Mathf.Pow(10,5);
    
    //-------------------------
    // R O T A T I O N.
    //-------------------------
    
    current_angle = front_transform.eulerAngles.z - _rigid_body.transform.eulerAngles.z;
    
    current_angle = (Mathf.Abs(current_angle) > 180) ? ((Mathf.Abs(current_angle) - 360) * Mathf.Sign(current_angle)) : current_angle;
    
    current_angle += Mathf.Sign(current_steering_angle) * Utils.curve_map_linear(0, 45, min_angle, max_angle, Mathf.Abs(current_steering_angle), 1);
    
    _rigid_body.transform.RotateAround(front_transform.position, Vector3.forward, current_angle);
    
    //-------------------------
    // S P E E D.
    //-------------------------
    
    Vector3 velocity = _rigid_body.transform.InverseTransformVector(_rigid_body.velocity);
    if (velocity.y < 0){
        velocity.y = 0;
    }
    _rigid_body.velocity = _rigid_body.transform.TransformVector(velocity);
    
    }
    

我想知道如何真正实现统一的目标。我是这个统一的东西的新手。我四处张望,有很多3D汽车的东西,但自上而下的东西不多。感谢任何形式的反馈。

1 个答案:

答案 0 :(得分:1)

使其不运动,移除前轮胎的刚体并使前轮胎成为底盘的孩子。

处理位置:

采用一种方法来查看汽车的当前位置,玩家转弯的角度并返回汽车在适当的圆周上行驶所需的切线速度:

Vector2 GetTangentialVelocity(...) { }

然后,找到该速度与底盘当前速度之间的差:

Vector2 velDiff = GetTangentialVelocity(...) - chassis_rigidbody.velocity;

然后,将AddForceForceType.VelocityChange应用于差异:

chassis_rigidbody.AddForce(velDiff, ForceType.VelocityChange);

处理旋转:

将重心向前移动。您可以通过加长刚体并将对撞机放在对象的后部或设置RigidBody.centerOfMass来实现此目的:

chassis_rigidbody.centerOfMass = Vector2.up * 0.5;

使函数类似于GetTangentialVelocity,该函数返回所需的角速度,找到与chassis_rigidbody.angularVelocity的差,然后将AddTorqueForceType.VelocityChange一起使用:

Vector2 angVelDiff = GetAngularVelocity(...) - chassis_rigidbody.angularVelocity;
chassis_rigidbody.AddTorque(angVelDiff , ForceType.VelocityChange);