Как сделать так, чтобы персонаж мог передвигать предметы в Unity2D
Нужно сделать так, чтобы персонаж мог передвигать предметы с Box Collider 2D в Uniy 2D, то есть игрок подходит сбоку к "Коробке", нажимает на кнопу, после чего персонаж двигается вместе с этим предметом. Я не нашёл ничего похожего в открытом доступе, возможно плохо искал. Сам я новичок и в Unity, и в C#, поэтому если не сложно, подскажите, пожалуйста, как можно реализовать передвижение предметов. Заранее спасибо. Вот код передвижения персонажа:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour
{
public float speed;
public float groundRadius;
public Transform groundCheck;
public LayerMask groundMask;
public float jumpForce;
private Rigidbody2D rb;
private Animator animWalk, animJump;
private bool isGround;
private float x;
void Start()
{
rb = GetComponent<Rigidbody2D>();
animWalk = GetComponent<Animator>();
animJump = GetComponent<Animator>();
}
void Update()
{
Move();
PickUp();
}
void Move()
{
isGround = Physics2D.OverlapCircle(groundCheck.position, groundRadius, groundMask);
float x = Input.GetAxis("Horizontal") * speed;
if (!isGround)
{
rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
}
else if (isGround)
{
rb.velocity = new Vector2(x, rb.velocity.y);
}
if (Input.GetKeyDown(KeyCode.Space) && isGround)
{
rb.AddForce(Vector2.up * jumpForce);
}
if (!isGround)
{
animJump.SetBool("IsJump", true);
}
else
{
animJump.SetBool("IsJump", false);
}
if (x != 0)
{
animWalk.SetBool("IsWalk", true);
}
else
{
animWalk.SetBool("IsWalk", false);
}
if (x < 0 && isGround)
{
rb.transform.rotation = Quaternion.Euler(0, 180, 0);
}
else if (x > 0 && isGround)
{
rb.transform.rotation = Quaternion.Euler(0, 0, 0);
}
}
private bool isPickup;
private float distance = 1f;
RaycastHit2D hit;
void PickUp()
{
if (Input.GetKey(KeyCode.W))
{
if (!isPickup)
{
Physics2D.queriesStartInColliders = false;
hit = Physics2D.Raycast(transform.position, Vector2.right * transform.localScale.x, distance);
if (hit.collider != null);
{
isPickup = true;
}
}
}
if (isPickup)
{
}
}
}
Ответы (2 шт):
Делайте рейкаст из головы игрока и ограничьте ему длину, что бы игрок не мог брать объекты, которые находятся слишком далеко. Проверяйте если рейкаст попал в объект с тегом pickupable_item, который надо добавить всем предметам, которые можно поднять, то надо проверяйте нажата ли кнопка, если да то делаем предмет ребёнком игрока.
По желанию в скрипте игрока можете добавить перемещение объекта при повороте.
Хочу добавить к ответу farkon00, Если хотите чтобы предмет ещё плавно двигался как в Амнезии, например, можно сделать Empty GameObject ребёнком тела игрока, назвав его, например, hand и воспользоваться интерполяцией (Vector2.Lerp):
bool characterGrabItem = false;
float itemMovementSpeed = 3.0f;
Transform? item;
// Вызывайте, когда нажимаете на кнопку действия (берёте предмет или бросаете его)
void GrabItem()
{
if(characterGrabItem)
{
// Если персонаж держит предмет - сбросить его. И там ниже ещё стейт меняется.
item = null;
}
else
{
// Здесь рейкаст и TryGetComponent и назначайте трансформ
//компонента в item, или если ничего не нашли рейкастом - return;
//...
}
// переключение состояния удержания предмета.
characterGrabItem = !characterGrabItem;
}
void FixedUpdate()
{
if (item is not null && characterGrabItem){
item.position = Vector2.Lerp(item.position, hand.position, itemMovementSpeed * Time.deltaTime);
}
}
// Ну и чутка доработать можно и со значениями поиграться чтобы коллизию не ломать.