# RaycastManager

namespace **`using Game.TouchRaycasters;`**

## How it works

**Raycast manager** prefab **holds all raycasters** that *you can switch*.\
By default in init project just one implementation of raycaster and it's **InteractObjectsRaycaster.**

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2FHibqMoOre0CHmIli92Rl%2Fimage.png?alt=media&#x26;token=00a4a1f7-58e8-49b2-947e-d5186effe8d2" alt=""><figcaption><p>Inspector of RaycastManager prefab</p></figcaption></figure>

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2FrAyXCNv2Z5VpbqFhTQol%2Fimage.png?alt=media&#x26;token=41fe721e-b9f5-4bca-a014-b29c86374711" alt=""><figcaption><p>Diagram of references</p></figcaption></figure>

{% hint style="danger" %}
To use touch raycasters implementatios -> you must replace [**InputUpdater** ](https://reddycat.gitbook.io/base-project-cube-doc/fundamentals/singletons/lean-touch)prefab in scene.
{% endhint %}

RaycastManager will not in DontDestroyOnLoad scene, you you need replace it everywhere you want to use it. Here is how quickly add RaycastManager+InputUpdater prefabs by GameObject create menu:

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2FWq7WUdhDFrIIUzSzFMJM%2Fimage.png?alt=media&#x26;token=8c2423d4-9ec5-4461-96b3-fad6116b1380" alt=""><figcaption><p>Right mouse click on Hierarchy widnow</p></figcaption></figure>

### TouchRaycaster (base class) for raycasters

Each TouchRaycaster has following properties:

* Layer Mask -> what physics layers raycast will check
* Racast Max Distance -> distance that raycast will go through
* \[ReadOnly in inspector] IsSubscribed to events bool -> used for debug purposes. If true -> raycast in use.
* UseRaycaster -> if true, then it will be subscribed to touch events and do raycast on events.\
  if false - it will unsubscribe from touch events and do nothing.

## InteractObjectsRaycaster implementation

It's **inheritance** from **TouchRaycaster** and it looks for **InteractObjects.**\
Here is diagram:

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2F7tOJ6pbcJvUCT12VldXh%2Fimage.png?alt=media&#x26;token=caec572d-f7fb-40f6-b1da-5bf4d03d5fe8" alt=""><figcaption></figcaption></figure>

InteractObjectsRaycaster looks for objects that inherited from InteractObject. It can be, for example, door. If we click on door -> raycaster will call virtual DoInteract() method from InteractObject class. \
So we can implement logic for door -> in DoInteract() we will play open animation and then call StopInteract in door itself. \
On StopInteract InteractObjectRaycaster current interaction object will be nulled.

{% hint style="warning" %}
InteractObjectsRaycasters works on drag events, means it will trigger InteractObject on touch down event and free it on touch up event (IteractObject can free itself it will call StopInteract() by itsefl).
{% endhint %}

{% hint style="info" %}
If you need special raycasters that raycasts for example every frame and etc, then implement new one. See Examples folder in project.
{% endhint %}

## API InteractObject

{% code lineNumbers="true" %}

```csharp
public abstract class InteractObject : MonoBehaviour {
    /// <summary>
    /// If true then this object is being interacted by player
    /// </summary>
    public bool IsInProgress => inProgress;

    /// <summary>
    /// Implement it to know if object locked for interactions
    /// </summary>
    public abstract bool CanInteract();

    /// <summary>
    /// This method start object interaction <br>
    /// Override it and you can implement different behaviours while interacting with object, call base() too then</br>
    /// </summary>
    /// <param name="onInteractionStop">This is callback when interaction stops</param>
    public virtual void DoInteract(UnityAction onInteractionStop = null);

    /// <summary>
    /// Call this method to stop interaction <br>
    /// Override it to make custom logic, call base() too then</br>
    /// </summary>
    public virtual void StopInteract();

    /// <summary>
    /// Here you can subscribe on stop interact callback after interaction started
    /// </summary>
    public void AppendOnStopCallback(UnityAction onInterationStop);
}
```

{% endcode %}

## API InteractObjectsRaycaster

{% code lineNumbers="true" %}

```csharp

/// <summary>
/// Interactions with the <see cref="InteractObject"/> 
/// mostly in <see cref="InteractPoint"/> but can be used anywere else
/// </summary>
public class InteractObjectsRaycaster : TouchRaycaster {
    /// <summary>
    /// InteractObject can be null if <see cref="doInteractOnRaycast"/> set to true
    /// </summary>
    public static UnityEvent<InteractObject> OnInteractibleObjFound;
    /// <summary>
    /// Current running interaction with InteractObject <br>
    /// If you manualy change InteractObject, then old one will be Stopped</br>
    /// </summary>
    public InteractObject CurrentInteraction;

    /// <summary>
    /// If true, raycast will go from camera to touch position direction<br>
    /// If false, raycast will go always to <see cref="RaycastViewPortPosition"/></br>
    /// </summary>
    public bool RaycastToTouchPosition;
    /// <summary>
    /// Normalized view port position that raycast will go from camera to<br>
    /// <b>Only if</b> <see cref="RaycastToTouchPosition"/> is false</br>
    /// </summary>
    public Vector3 RaycastViewPortPosition;

    // field in inspector
    [SerializeField, 
    Tooltip("If raycast finds interact object, should it auto start interaction")]
    private bool doInteractOnRaycast = true;

    // from base class:
    /// <summary>
    /// if true, then it will be subscribed to touch events 
    /// and do raycast on events<br>
    /// if false - it will unsubscribe from touch events and do nothing</br>
    /// </summary>
    public bool UseRaycaster;
            
    /// <summary>
    /// By default it's false. 
    /// If false then raycast will work only on touch down event<br>
    /// If true then raycast will work also on touch move events</br>
    /// </summary>
    public bool UseTouchMoveRaycasts;
}
```

{% endcode %}

## API RaycastManager

By raycast manager you will change active raycaster.

```csharp

public class RaycastManager : MonoBehaviour {
    public static RaycastManager instance;
    /// <summary>
    /// Raycaster that is currently active
    /// </summary>
    public TouchRaycaster ActiveRaycaster => activeRaycaster;

    /// <summary>
    /// Enables only one raycaster by type
    /// </summary>
    /// <typeparam name="T">Raycaster type (class)</typeparam>
    public void EnableOnly<T>() where T : TouchRaycaster;

    /// <summary>
    /// Enables only one raycaster
    /// </summary>
    /// <typeparam name="newRaycaster">Raycaster object</typeparam>
    public void EnableOnly(TouchRaycaster newRaycaster);

    /// <summary>
    /// Disables active raycaster if it's not null
    /// </summary>
    public void DisableActiveRaycaster();

    /// <summary>
    /// Disables raycaster object if it's active
    /// </summary>
    /// <param name="raycaster"></param>
    public void Disable(TouchRaycaster raycaster)
}
```

Examples how to use this RaycastManager in **Assets/\_Main/\_Examples/Raycast Manager/Example.scene**
