我是Raycasting的新手,所以我可能会做错事,但我想向游戏对象所面对的方向发送一个射线广播,在它击中的第一个对象上反弹,并在消失前走一段短距离。
据我所知,Unity中没有内置的反射射线广播的功能,所以我一直在尝试在第一个射线广播击中的地方生成另一个射线广播,但我的运气并不好。以下是我目前的做法。
public Gameobject firePoint; // I have an object attached to my main object that I use as a point of origin
void DrawLazer()
{
Vector2 origin = new Vector2(firePoint.transform.position.x, firePoint.transform.position.y);
Vector2 direction = transform.TransformDirection(Vector2.up);
RaycastHit2D hit = Physics2D.Raycast(origin, direction, 10f);
Debug.DrawLine(origin, direction *10000, Color.black);
if (hit)
{
Debug.Log("Hit: " + hit.collider.name);
var whatWeHit = new Vector2(hit.transform.position.x, hit.transform.position.y);
var offset = whatWeHit + hit.point;
offset.y = 0;
RaycastHit2D hit2 = Physics2D.Raycast(offset, Vector3.Reflect(direction, hit.normal) * -10000);
if (hit2)
{
Debug.DrawLine(offset, -Vector3.Reflect(direction, hit.normal) * -10000);
}
}
}
我在更新中调用DrawLaxer();。
当前的脚本算是能够生成第二个射线广播,然而正如你所看到的,第一个射线广播在击中某个物体时仍然没有停止,更重要的是,虽然这个解决方案在击中水平面上的平面物体时效果不错。但如果它击中垂直或对角线平面上的物体时,它会在错误的轴上进行多次计算。
如果有任何帮助,我将非常感激
这里是一个完整的使用Vector2.Reflect和SphereCast的单行为例子。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ReflectionExample : MonoBehaviour
{
public GameObject firePoint;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
DrawPredictionDisplay();
}
private void DrawPredictionDisplay()
{
Vector2 origin = firePoint.transform.position; //unity has a built in type converter that converts vector3 to vector2 by dropping the z component
Vector2 direction = firePoint.transform.up;
float radius = 1.0f;
RaycastHit2D distanceCheck = Physics2D.Raycast(origin, direction);
RaycastHit2D hit = Physics2D.CircleCast(origin, radius, direction);
Debug.DrawLine(origin, direction * 10000, UnityEngine.Color.black);
DrawCircle(origin, 1.0f, UnityEngine.Color.black);
if (hit)
{
origin = hit.point + (hit.normal * radius);
direction = Vector2.Reflect(direction, hit.normal);
hit = Physics2D.CircleCast(origin, radius, direction);
Debug.DrawLine(origin, direction * 10000, UnityEngine.Color.blue);
DrawCircle(origin, 1.0f, UnityEngine.Color.blue);
}
}
private void DrawCircle(Vector2 center, float radius, UnityEngine.Color color)
{
Vector2 prevPoint = new Vector2(Mathf.Sin(0f), Mathf.Cos(0f));
for (float t = 0.1f; t < 2 * Mathf.PI; t = t + 0.1f)
{
var nextPoint = new Vector2(Mathf.Sin(t), Mathf.Cos(t));
Debug.DrawLine(center + prevPoint, center + nextPoint, color);
prevPoint = nextPoint;
}
}
}