【问题标题】:Unity 3D: How I can make a Player with a Character Controller can push another Player with Character Controller?Unity 3D:如何让一个拥有角色控制器的玩家可以推动另一个拥有角色控制器的玩家?
【发布时间】:2019-12-11 19:42:33
【问题描述】:

我是 Unity 新手,我正在学习教程。我正在制作一个使用 CharacterController 移动 3D 播放器的脚本,并且我附加了另一个脚本,该脚本添加了推动 RigidBodys 的能力,但是如何让 Player 推动另一个 Player?它只是碰撞,但没有任何反应,我不想让它成为刚体。

//Script that i use as PlayerController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{

    public float horizontalMove;
    public float verticalMove;
    private Vector3 playerInput;

    public CharacterController player;

    public float playerSpeed;
    public Vector3 movePlayer;
    public float gravity = 9.8f;
    public float fallVelocity;
    public float jumpForce;

    public Camera mainCamera;
    private Vector3 camForward;
    private Vector3 camRight;

    public bool isOnSlope = false;
    private Vector3 hitNormal;
    public float slideVelocity;
    public float slopeForceDown;
    private PushRigidBody pushRigid;
    public float pushPlus;


    // Start is called before the first frame update
    void Start()
    {
        player = GetComponent<CharacterController>();
        //Obtengo el componente Script "PushRigidBody" para poder usar sus metodos y cambiar variables con sus mutadores
        pushRigid = GetComponent<PushRigidBody>();
    }

    // Update is called once per frame
    void Update()
    {
        horizontalMove = Input.GetAxis("Horizontal");
        verticalMove = Input.GetAxis("Vertical");

        playerInput = new Vector3(horizontalMove, 0, verticalMove);
        playerInput = Vector3.ClampMagnitude(playerInput, 1);

        camDirection();

        movePlayer = playerInput.x * camRight + playerInput.z * camForward;

        movePlayer = movePlayer * playerSpeed;

        player.transform.LookAt(player.transform.position + movePlayer);

        SetGravity();


        PlayerSkills();
        player.Move(movePlayer * playerSpeed * Time.deltaTime);


    }
    private void FixedUpdate()
    {

    }

    void camDirection()
    {
        camForward = mainCamera.transform.forward;
        camRight = mainCamera.transform.right;

        camForward.y = 0;
        camRight.y = 0;

        camForward = camForward.normalized;
        camRight = camRight.normalized;
    }

    //Funcion para habilidades de jugador
    public void PlayerSkills()
    {
        if (player.isGrounded && Input.GetButtonDown("Jump"))
        {

            fallVelocity = jumpForce;
            movePlayer.y = fallVelocity;

        }
        //Detecta si presiono la tecla para golpear objeto y aventarlo, si la aprieta aumenta la fuerza con la que golpea, si no, la vuelve a dejar como estaba
        if (Input.GetButton("Fire1"))
        {
            pushRigid.SetPushPower(pushPlus);
        }
        else
        {
            pushRigid.SetPushPower( 0f );
        }

    }

    void SetMov(Vector3 vector)
    {
        movePlayer = movePlayer - vector;
    }

    void SetGravity()
    {

        if (player.isGrounded)
        {
            fallVelocity = -gravity * Time.deltaTime;
            movePlayer.y = fallVelocity;
        }
        else
        {
            fallVelocity -= gravity * Time.deltaTime;
            movePlayer.y = fallVelocity;
        }

        SlideDown();
    }
    //Compara si esta o no en una rampa y aplica fuerzas para deslizar
    public void SlideDown()
    {
        //isOnSlope = angulo >= angulo maximo del charcontroller
        isOnSlope = Vector3.Angle(Vector3.up, hitNormal) >= player.slopeLimit;

        if (isOnSlope)
        {
            movePlayer.x += ((1f - hitNormal.y) * hitNormal.x) * slideVelocity;
            movePlayer.z += ((1f - hitNormal.y) * hitNormal.z) * slideVelocity;

            movePlayer.y += slopeForceDown;

        }

    }

    private void OnControllerColliderHit(ControllerColliderHit hit)
    {
        hitNormal = hit.normal;
    }
}


----------


///Script that i use for push rigidbodys
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PushRigidBody : MonoBehaviour
{

    public float pushPower = 2.0f;
    private float pushPowerPlus = 0f;


    private void OnControllerColliderHit(ControllerColliderHit hit)
    {
        Rigidbody body = hit.collider.attachedRigidbody;


        if (body == null || body.isKinematic)
        {

            return;
        }

        //Si caemos encima de un objeto no queremos empujarlo, se pone encima de el
        if (hit.moveDirection.y < -0.8)
        {
            return;
        }

        Vector3 pushDir = new Vector3(hit.moveDirection.x, 0, hit.moveDirection.z);
        ;

        body.velocity = pushDir * (pushPower + pushPowerPlus);

    }

    public void SetPushPower(float pushPowerVar)
    {
        pushPowerPlus = pushPowerVar;
    }


}

【问题讨论】:

  • 对碰撞施加力

标签: unity3d rigid-bodies


【解决方案1】:

如果您不想使用RigidBody 来移动角色,那么如果您也不使用RigidBody 进行推送会更容易,并像使用body.move 那样实现它更新(强制身体在每个游戏刻移动)

因此,您可以为玩家添加一个新的矢量,即推力,并在您碰撞时设置与您碰撞的其他玩家的推力矢量。

然后在更新时,您在调用move 时将推向量添加到运动中,并使其降低直到达到 0 以创建减速的感觉。

您可以使用 Unity (Lerp) 中内置的线性插值来使这个“向量平滑地归零”。

【讨论】:

    【解决方案2】:

    有两种方法可以做到这一点 1. 将 Collider 和rigidBody(两者都需要)添加到要推送的对象和将要推送的对象中它向他们移动。 2. 如果您想在某个事件发生时推送对象,您可以执行上述所有操作,但在事件发生时您可以使用 Rigidbody 的 AddForce RigidBody.AddForce 功能。

    祝你好运!

    编辑:我相信 CharachterController 在 GameObjects 中充当碰撞器,因此您可能不需要添加碰撞器。

    【讨论】:

      猜你喜欢
      • 2017-09-11
      • 1970-01-01
      • 1970-01-01
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-17
      • 1970-01-01
      相关资源
      最近更新 更多