Unity 3D: как сделать так, чтобы игрок с контроллером персонажа мог толкать другого игрока с контроллером персонажа?

Я новичок в единстве и следую инструкциям. Я делаю скрипт, который перемещает 3D-плеер с помощью CharacterController, и я прикрепил еще один скрипт, который добавляет возможность толкать 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;
    }


}

person Jesus Sanchez    schedule 11.12.2019    source источник
comment
применить силу при столкновении   -  person AgentFire    schedule 11.12.2019


Ответы (2)


Если вы не хотите использовать RigidBody для перемещения персонажа, будет проще, если вы также не будете использовать RigidBody для толкания, а реализуете его так же, как вы использовали body.move в обновлении (которое заставляет тело двигаться каждый раз). тик игры)

Таким образом, вы можете добавить новый вектор к игрокам, силу толчка, и когда вы столкнетесь, вы зададите вектор силы толчка другого игрока, с которым вы столкнулись.

Затем при обновлении вы добавляете вектор толчка к движению при вызове move и делаете его ниже, пока он не достигнет 0, чтобы создать ощущение замедления.

Вы можете использовать встроенную линейную интерполяцию в Unity (Lerp), чтобы этот вектор плавно уменьшался до нуля.

person Gabriel Slomka    schedule 11.12.2019

Два способа сделать это 1. Добавить Collider и RigidBody (оба обязательны) к объекту, который будет толкать, и к объекту, который будет толкать, и использовать MovePosition RigidBody.MovePosition для перемещения объекта, который будет толкать, а затем будет толкать физический движок Unity других твердых тел, когда он движется к ним. 2. Если вы хотите подтолкнуть объекты при определенном событии, вы можете сделать все вышеперечисленное, но при возникновении события вы можете использовать AddForce RigidBody.AddForce.

Удачи!

Редактировать: я считаю, что CharachterController действует как коллайдер в GameObjects, поэтому вам может не понадобиться добавлять коллайдеры.

person rob1997    schedule 12.12.2019