创建自上而下的 2D 鞭子机制
Creating top down 2D whip mechanic
What Whip should look like
我正在尝试创建一个鞭子,它可以在按下某个按钮后向鼠标面向的任何方向延伸。如果路上有“可抓取”的物体,例如敌人或盒子,它应该抓住这些物体并将它们拉来拉去与其他物体碰撞一定时间。
我知道我需要鞭子伸出和锁定的不同 sprite 镜头来制作动画,但我不知道如何在代码中实现这一点,也不知道如何让鞭子在检测到“可抓取”对象时停下来。
将此脚本附加到您的播放器,这应该可以完成工作:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public Transform player = null;
public float speed = 30f;
public string grabbableTag = "grabbable";
private LineRenderer line = null;
private float timer = 0f;
private bool grabbing = false;
private bool reached = false;
private Vector2 from = Vector2.zero;
private Vector2 to = Vector2.zero;
private Vector2 target = Vector2.zero;
private Transform grabbable = null;
private void Start()
{
player = transform;
line = new GameObject("Line").AddComponent<LineRenderer>();
line.startColor = Color.red;
line.endColor = Color.red;
// Assign a material
line.gameObject.SetActive(false);
reached = false;
grabbing = false;
}
private void Update()
{
if(grabbing)
{
Grabbing();
}
else
{
if (Input.GetMouseButtonDown(0))
{
Grab();
}
}
}
private void Grab()
{
Vector3 mousePosition = Input.mousePosition;
mousePosition.z = Vector3.Distance(player.position, Camera.main.transform.position);
to = Camera.main.ScreenToWorldPoint(mousePosition);
from = player.position;
Vector2 direction = (to - from).normalized;
float distance = Vector2.Distance(from, to);
RaycastHit2D[] hits = Physics2D.RaycastAll(from, direction, distance);
grabbable = null;
for (int i = 0; i < hits.Length; i++)
{
if (hits[i].transform.tag == grabbableTag)
{
grabbable = hits[i].transform;
break;
}
}
if (grabbable != null)
{
distance = Vector2.Distance(player.position, grabbable.position);
to = from + direction * distance;
}
grabbing = true;
reached = false;
target = from;
timer = 0;
line.gameObject.SetActive(true);
line.positionCount = 2;
line.SetPosition(0, from);
line.SetPosition(1, from);
}
private void Grabbing()
{
if (reached)
{
target = Vector2.Lerp(target, from, speed * Time.deltaTime);
if (target == from)
{
GrabDone(grabbable);
grabbing = false;
line.gameObject.SetActive(false);
}
}
else
{
target = Vector2.Lerp(target, to, speed * Time.deltaTime);
if(target == to)
{
reached = true;
}
}
line.SetPosition(1, target);
if (reached && grabbable != null)
{
grabbable.position = target;
}
}
private void GrabDone(Transform grabbed)
{
if(grabbed != null)
{
// Do somthing ...
Destroy(grabbed.gameObject);
}
}
}
What Whip should look like
我正在尝试创建一个鞭子,它可以在按下某个按钮后向鼠标面向的任何方向延伸。如果路上有“可抓取”的物体,例如敌人或盒子,它应该抓住这些物体并将它们拉来拉去与其他物体碰撞一定时间。 我知道我需要鞭子伸出和锁定的不同 sprite 镜头来制作动画,但我不知道如何在代码中实现这一点,也不知道如何让鞭子在检测到“可抓取”对象时停下来。
将此脚本附加到您的播放器,这应该可以完成工作:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public Transform player = null;
public float speed = 30f;
public string grabbableTag = "grabbable";
private LineRenderer line = null;
private float timer = 0f;
private bool grabbing = false;
private bool reached = false;
private Vector2 from = Vector2.zero;
private Vector2 to = Vector2.zero;
private Vector2 target = Vector2.zero;
private Transform grabbable = null;
private void Start()
{
player = transform;
line = new GameObject("Line").AddComponent<LineRenderer>();
line.startColor = Color.red;
line.endColor = Color.red;
// Assign a material
line.gameObject.SetActive(false);
reached = false;
grabbing = false;
}
private void Update()
{
if(grabbing)
{
Grabbing();
}
else
{
if (Input.GetMouseButtonDown(0))
{
Grab();
}
}
}
private void Grab()
{
Vector3 mousePosition = Input.mousePosition;
mousePosition.z = Vector3.Distance(player.position, Camera.main.transform.position);
to = Camera.main.ScreenToWorldPoint(mousePosition);
from = player.position;
Vector2 direction = (to - from).normalized;
float distance = Vector2.Distance(from, to);
RaycastHit2D[] hits = Physics2D.RaycastAll(from, direction, distance);
grabbable = null;
for (int i = 0; i < hits.Length; i++)
{
if (hits[i].transform.tag == grabbableTag)
{
grabbable = hits[i].transform;
break;
}
}
if (grabbable != null)
{
distance = Vector2.Distance(player.position, grabbable.position);
to = from + direction * distance;
}
grabbing = true;
reached = false;
target = from;
timer = 0;
line.gameObject.SetActive(true);
line.positionCount = 2;
line.SetPosition(0, from);
line.SetPosition(1, from);
}
private void Grabbing()
{
if (reached)
{
target = Vector2.Lerp(target, from, speed * Time.deltaTime);
if (target == from)
{
GrabDone(grabbable);
grabbing = false;
line.gameObject.SetActive(false);
}
}
else
{
target = Vector2.Lerp(target, to, speed * Time.deltaTime);
if(target == to)
{
reached = true;
}
}
line.SetPosition(1, target);
if (reached && grabbable != null)
{
grabbable.position = target;
}
}
private void GrabDone(Transform grabbed)
{
if(grabbed != null)
{
// Do somthing ...
Destroy(grabbed.gameObject);
}
}
}