# Implementing Door

<details>

<summary>1 - Create DoorInteract class, inherit it from IteractObject</summary>

also override DoInteract and StopInteract methods to make custom interact logic. You will have this:

{% code lineNumbers="true" %}

```csharp
                                // inherit and implement abstract method
                                // inherit must be or InteractObjectsRaycaster will not find your obj!
public class DoorInteract_Example : InteractObject {
    public override bool CanInteract() {
        // we will implement it next step
    }

    // override this method to make custom interact logic
    public override void DoInteract(UnityAction onInteractionStop = null) {
        base.DoInteract(onInteractionStop);
    }

    // override this method to make custom interact logic
    public override void StopInteract() {
        base.StopInteract();
    }
}
```

{% endcode %}

</details>

<details>

<summary>2 - Implement open and close process</summary>

{% code lineNumbers="true" %}

```csharp
// inherit and implement abstract method
// inherit must be or InteractObjectsRaycaster will not find your obj!
public class DoorInteract_Example : InteractObject {
    [SerializeField] private float _openTime = 1f;
    [SerializeField] private AnimationCurve _openCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
    [Space(5f)]
    [SerializeField] private float _closeTime = 1f;
    [SerializeField] private AnimationCurve _closeCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
    [Space(5f)]
    [SerializeField] private float _openAngle = 90f;

    [SerializeField] private Transform _doorPivot;
    private Quaternion _initDoorRot;

    // we can open door and we also can close it
    private Coroutine _openOrCloseProcess;
    private bool _isDoorClosed = true;

    private void Awake() {
        // remember init rotation
        _initDoorRot = _doorPivot.localRotation;
    }

    public override bool CanInteract() {
        return true; // let's say we can interact with door always
    }

    // override this method to make custom interact logic
    public override void DoInteract(UnityAction onInteractionStop = null) {
        base.DoInteract(onInteractionStop);

        CoroutineHelper.Stop(ref _openOrCloseProcess);

        // if closed -> open
        if (_isDoorClosed) {
            _openOrCloseProcess = StartCoroutine(Open());
        }
        else {
            _openOrCloseProcess = StartCoroutine(Close());
        }

        // change door state flag
        _isDoorClosed = !_isDoorClosed;

        // this is one click interaction so we will stop it immediately
        StopInteract();
    }

    // override this method to make custom interact logic
    public override void StopInteract() {
        base.StopInteract();
    }

    // open door process
    IEnumerator Open() {
        // remember start and target rotations before lerp
        Quaternion _startRot = _doorPivot.localRotation;
        Quaternion _targetRot = _initDoorRot * Quaternion.Euler(0f, _openAngle, 0f);
        for (float i = 0f; i < 1f; i += Time.deltaTime / _openTime) {
            _doorPivot.localRotation = Quaternion.Slerp(_startRot, _targetRot, _openCurve.Evaluate(i));
            yield return null;
        }

        _doorPivot.localRotation = _targetRot;
    }

    // close door process
    IEnumerator Close() {
        // remember start and target rotations before lerp
        Quaternion _startRot = _doorPivot.localRotation;
        Quaternion _targetRot = _initDoorRot;
        for (float i = 0f; i < 1f; i += Time.deltaTime / _closeTime) {
            _doorPivot.localRotation = Quaternion.Slerp(_startRot, _targetRot, _closeCurve.Evaluate(i));
            yield return null;
        }

        _doorPivot.localRotation = _targetRot;
    }
}
```

{% endcode %}

</details>

<details>

<summary>3 - Enable raycaster before interact</summary>

By default no one raycaster is running, you need to enable target raycaster manualy before any interactions. \
\
Here is example, I will write RaycastStart.cs script that will enable TouchRaycaster by type on scene start. But you should enable it by triggers or in game manager.

```csharp
public class RaycasterStart : MonoBehaviour {
    // Start is called before the first frame update
    void Start() {
        RaycastManager.instance.EnableOnly<InteractObjectsRaycaster>();
    }
}
```

</details>

<details>

<summary>4 - Setup door obj (imgs below)</summary>

Replace DoorInteract.cs on object (mesh) with collider. \
Set target layer of object (I will use Default layer in think example)

</details>

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2FAls92I6OwQUk47u31E8K%2Fimage.png?alt=media&#x26;token=2e816e73-ed0d-4853-b8d3-6278ecb32cc7" alt=""><figcaption><p>Door obj setup</p></figcaption></figure>

That's all. This is simple door that opens/closes on click by raycasts.

You can find this implementation in **Assets/\_Main/\_Examples/Raycast Manager/Example.scene**
