Reputation: 135
I'm trying to accurately reflect a LaserBeam off a wall/collider. The Laser Beam is fired from a LaserGun and is small, measuring around 2.
So I have currently set my LaserBeam as a 3D Capsule and coloured it red. Its pretty ugly, but I'm not too concerned just now.
Whenever the LaserBeam collides with an Object/Wall it doesn't rebound as I would like. I suppose it would have to be completely absorbed by the wall/collider so that the direction would be pointing the correct way.
The image in the website below should explain what I'm trying to achieve. http://answers.unity3d.com/questions/631311/making-an-object-bounce-off-a-wall-the-same-way-li.html (If the LaserBeam was an Arrow. And the arrow is the InDirection and once the Arrow has collided with the wall, it would be in the direction of the Result).
I have set both the Drag and AngularDrag to 0. In my Capsule material. Dynamic and Static Friction is set to 0. Bounciness is 1. FrictionCombine is Min and BounceCombine is Max.
I'm wondering if I have to change the 3D Capsule to a LineRenderer?
Any help would be greatly appreciated.
Upvotes: 0
Views: 1143
Reputation: 3629
This script detects collisions solely using Raycasts. It first does a Raycast at its (the lasers) tip, testing if it collides with anything. If it does, it spawns a reflected version of itself. Also it does q Raycast at its end, to test if it completely penetrated a collider. If so, it destroys itself. The result is a pretty realistic laser beam that even "bends" on collision while keeping its total length.
The script assumes
wallLayers
wallLayers
The script will
speedOfLight
units per secondTest it out, it's fun:
using UnityEngine;
[RequireComponent(typeof(CapsuleCollider))]
public class LaserBeam : MonoBehaviour
{
public LayerMask wallLayers;
public float speedOfLight = 1f;
private Vector3 reflectionTestPointLocal, completeIntrusionTestPointLocal;
private float beamLengthLocal;
private bool didSpawnReflection;
void Awake()
{
CapsuleCollider capsuleCollider = GetComponent<CapsuleCollider>();
beamLengthLocal = capsuleCollider.height;
reflectionTestPointLocal = Vector3.up * beamLengthLocal * .5f;
completeIntrusionTestPointLocal = -Vector3.up * beamLengthLocal * .5f;
}
void Update()
{
float stepLength = speedOfLight * Time.deltaTime;
Travel(stepLength);
}
private void Travel(float stepLength)
{
Vector3 step = transform.up * stepLength;
if (!didSpawnReflection)
{
RaycastHit hit;
if (Physics.Raycast(transform.TransformPoint(reflectionTestPointLocal), step, out hit, stepLength, wallLayers))
{
SpawnReflection(hit.point, hit.normal, stepLength - hit.distance);
didSpawnReflection = true;
}
}
if (didSpawnReflection)
{
RaycastHit hit;
if (Physics.Raycast(transform.TransformPoint(completeIntrusionTestPointLocal), step, out hit, stepLength, wallLayers))
{
Destroy(gameObject);
}
}
transform.position += step;
}
private void SpawnReflection(Vector3 pointOfReflection, Vector3 reflectionNormal, float intrusion)
{
float impactAngle = Vector3.Angle(-transform.up, reflectionNormal);
Vector3 impactTangent = Vector3.Cross(-transform.up, reflectionNormal);
Quaternion reflectedRotation = Quaternion.AngleAxis(180 + impactAngle * 2, impactTangent) * transform.rotation;
LaserBeam reflectedBeam = Instantiate(this);
reflectedBeam.gameObject.name = gameObject.name;
reflectedBeam.transform.parent = transform.parent;
reflectedBeam.transform.localScale = transform.localScale;
reflectedBeam.transform.rotation = reflectedRotation;
reflectedBeam.transform.position = pointOfReflection - reflectedBeam.transform.TransformVector(Vector3.up * beamLengthLocal * .5f);
reflectedBeam.Travel(intrusion);
}
}
Upvotes: 1
Reputation: 2157
Have you tried using a TrailRenderer component?
This way you would have your "Laser" set up as a small sphere (which size will be your lasers width): on this object, you'll have the following componennts:
To "fire" a laser you simply have to set this object as a prefab and instantiate it at a given position, afterward simply set the RigidBody velocity according to the desired speed/direction :)
One benefit of this method is you can easily register to OnCollision[...]
events and use them to your needs.
Hope this helps,
Upvotes: 0