using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
///
/// Checks for collisions with both the real and virtual world and moves forward each frame.
/// Inherit from this class to easily make your own projectile that can hit both the virtual and real.
/// See LaserShot_Drone and LaserShot_Player in the ZED Drone Battle sample for examples.
/// Real world "collisions" test if it's behind the real world using the static hit test functions in ZEDSupportFunctions.
///
public class ZEDProjectile : MonoBehaviour
{
///
/// How fast the projectile moves forward in meters per second.
///
[Tooltip("How fast the projectile moves forward in meters per second.")]
public float speed = 10f;
///
/// How long the projectile lasts before being destroyed, even if it doesn't collide with anything.
///
[Tooltip("How long the projectile lasts before being destroyed, even if it doesn't collide with anything.")]
public float lifespan = 8f;
///
/// How granular the dots are along the fake raycast done for real-world collisions.
///
[Tooltip("How granular the dots are along the fake raycast done for real-world collisions.")]
public float distanceBetweenRayChecks = 0.01f;
///
/// How far behind a real pixel can a collision check decide it's not a collision.
///
[Tooltip("How far behind a real pixel can a collision check decide it's not a collision.")]
public float realWorldThickness = 0.05f;
///
/// If true, all active ZEDs are used to check for collisions.
/// This can mean being able to shoot things that aren't visible to the first player, but due to the
/// nature of collisions testing if virtual objects are behind the real world, can lead to
/// false positives if, for instance, a player in pass-through AR is between a projectile and a third-person ZED.
/// Use the realWorldThickness value to help mitigate this.
///
[Tooltip("If true, all active ZEDs are used to check for collisions. " +
"This can mean being able to shoot things that aren't visible to the first player, but due to the " +
"nature of collisions testing if virtual objects are behind the real world, can lead to " +
"false positives if, for instance, a player in pass-through AR is between a projectile and a third-person ZED. " +
"Use the realWorldThickness value to help mitigate this.")]
public bool testCollisionsUsingAllZEDs = true;
///
/// Primary ZEDManager, used for collision detection when testCollisionsUsingAllZEDs is set to false.
///
public ZEDManager zedManager = null;
///
/// The ZED camera reference, used for calling ZEDSupportFunctions to transform depth data from the ZED into world space.
///
protected Camera cam;
private void Awake()
{
if (zedManager == null)
{
zedManager = FindObjectOfType();
//If this happenend when only using a primary ZED for collisions but there are multiple ZEDs, collisions will be
//calculated using an arbitrary camera. Warn the user.
if (testCollisionsUsingAllZEDs == false && ZEDManager.GetInstances().Count > 1)
{
Debug.LogWarning("Warning: ZEDProjectile's zedManager value was not specified, resulting in assigning to first available " +
" camera, but there are multiple cameras in the scene. This can cause strange collision test behavior.");
}
}
if (!cam)
{
cam = zedManager.GetMainCamera();
}
}
///
/// Handles movements and collisions on a constant basis.
///
void FixedUpdate()
{
//Calculate where the object should move this frame
Vector3 newpos = transform.position + transform.rotation * Vector3.forward * (speed * Time.deltaTime);
//Collisions with the real World. As the object moves, collisions checks are made each frame at the next position.
Vector3 collisionpoint;
Vector3 collisionnormal;
//First, test the primary ZED. Collisions will look the most accurate if calculated from this one.
bool primaryhit = ZEDSupportFunctions.HitTestOnRay(zedManager.zedCamera, cam, newpos, transform.rotation, Vector3.Distance(transform.position, newpos),
distanceBetweenRayChecks, out collisionpoint, false, realWorldThickness);
if (primaryhit)
{
//Call the function to resolve the impact. This allows us to easily override what happens on collisions with classes that inherit this one.
ZEDSupportFunctions.GetNormalAtWorldLocation(zedManager.zedCamera, collisionpoint, sl.REFERENCE_FRAME.WORLD, cam, out collisionnormal);
OnHitRealWorld(collisionpoint, collisionnormal);
}
if (!primaryhit && testCollisionsUsingAllZEDs) //If set to true, test the rest of the ZEDs as well.
{
foreach (ZEDManager manager in ZEDManager.GetInstances())
{
if (manager == zedManager) continue; //If it's the primary ZED, skip as we've already tested that one.
if (ZEDSupportFunctions.HitTestOnRay(manager.zedCamera, manager.GetMainCamera(), newpos, transform.rotation, Vector3.Distance(transform.position, newpos), distanceBetweenRayChecks, out collisionpoint, false, realWorldThickness))
{
//Call the function to resolve the impact. This allows us to easily override what happens on collisions with classes that inherit this one.
ZEDSupportFunctions.GetNormalAtWorldLocation(manager.zedCamera, collisionpoint, sl.REFERENCE_FRAME.WORLD, manager.GetMainCamera(), out collisionnormal);
OnHitRealWorld(collisionpoint, collisionnormal);
break; //No need to test the rest of the ZEDs.
}
}
}
//Collisions with virtual objects
//Cast a ray to check collisions between here and the intended move point for virtual objects.
RaycastHit hitinfo;
if (Physics.Raycast(transform.position, newpos - transform.position, out hitinfo, Vector3.Distance(transform.position, newpos)))
{
//Call the function to resolve the impact. This allows us to easily override what happens on collisions with classes that inherit this one.
OnHitVirtualWorld(hitinfo);
}
//Move it to this new place
transform.position = newpos;
//Tick down its lifespan and check if we should destroy it.
lifespan -= Time.deltaTime;
if (lifespan <= 0f)
{
Destroy(gameObject);
}
}
///
/// Called when the projectile hits real geometry. Override to spawn effects, play sounds, etc.
///
///
///
public virtual void OnHitRealWorld(Vector3 collisionpoint, Vector3 collisionnormal)
{
Destroy(gameObject);
}
///
/// Called when the projectile hits a virtual collider. Override to spawn effects, inflict damage, etc.
///
/// The RayCastHit supplied by the raycast used to detect the collision.
public virtual void OnHitVirtualWorld(RaycastHit hitinfo)
{
Destroy(gameObject);
}
}