Push Button 커스텀

VR/XR Interaction Toolkit 2024. 1. 7. 03:17
반응형

 

 

 

 

 


Push Button의 기본 구성 요소 (컴포넌트)

BoxColider (IsTrigger체크해제)

 

XRSimpleInteractable : XRBaseInteractable

호버 및 선택과 같은 상호 작용 상태에 대한 이벤트를 제공하는 가장 간단한 Interactable 개체입니다.

 

XRPokeFilter

기본 찌르기 기능을 허용하고 상호 작용 가능 항목이 선택되는 시기에 대한 제약 조건을 정의하는 필터 구성 요소입니다.

 

XRPokeFollowAffordance

XRPokeFilter와 같은 IPokeStateDataProvider에 대한 애니메이션 어포던스를 따릅니다.
찌른 위치를 따르는 버튼과 같은 누른 변환을 애니메이션하는 데 사용됩니다.


포크가 트리거될 수 있도록 하는 포크 ​​상호 작용 가능 상호 작용 축을 따른 거리입니다.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private bool isOn = false;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private XRPokeFilter filter;
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        filter = GetComponent<XRPokeFilter>();
        
        initBoxColliderCenter = _boxCollider.center;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            if (isOn)
            {   
                _hoverType = HoverType.OFF;    
            }
            else
            {
                _hoverType = HoverType.ON;
                _affordance.returnToInitialPosition = false;
            }
            
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (isOn == false)
            {
                _affordance.returnToInitialPosition = true;
                _boxCollider.center = initBoxColliderCenter;
                _hoverType = HoverType.NONE;
            }
        });
        
    }

    private void Update()
    {
        if (_interactable.isHovered && isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                isOn = true;
                Debug.Log("On");
            }
            else if(_hoverType == HoverType.OFF)
            {
                isOn = false;
                Debug.Log("Off");
                // if(coroutine != null) StopCoroutine(coroutine);
                // coroutine= StartCoroutine(ReturnToInitPosition());
                _hoverType = HoverType.NONE;
            }
        }
    }

    // private Coroutine coroutine;
    //
    // private IEnumerator ReturnToInitPosition()
    // {
    //     while (true)
    //     {
    //         _affordance.pokeFollowTransform.localPosition = Vector3.Lerp(_affordance.pokeFollowTransform.localPosition, new Vector3(0, 0.045f, 0), Time.deltaTime);
    //         if (_affordance.pokeFollowTransform.localPosition == new Vector3(0, 0.045f, 0))
    //             break;
    //         yield return null;
    //     }
    //     Debug.LogFormat("move complete");
    //     _boxCollider.center = initBoxColliderCenter;
    // }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            if (_isOn)
            {   
                _hoverType = HoverType.OFF;    
            }
            else
            {
                _hoverType = HoverType.ON;
                _affordance.returnToInitialPosition = false;
            }
            
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (_isOn == false)
            {
                _affordance.returnToInitialPosition = true;
                _boxCollider.center = initBoxColliderCenter;
                _hoverType = HoverType.NONE;
            }
        });
        
    }

    private void Update()
    {
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                _isOn = true;
                Debug.Log("On");
            }
            else if(_hoverType == HoverType.OFF)
            {
                _isOn = false;
                Debug.Log("Off");
                _hoverType = HoverType.NONE;
            }
        }
    }
}

45보다 작을때
45보다 클떄

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;
            var ray = new Ray(poke.attachTransform.position, poke.attachTransform.forward);
            //Debug.DrawRay(ray.origin, ray.direction, Color.red, 5f);
            var dot = Vector3.Dot(poke.attachTransform.forward, -_boxCollider.transform.up);
            Debug.LogFormat("{0}", dot);
                
            var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
            //Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

            // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
            var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

            Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
            if (angle > 45)
            {
                Debug.LogFormat("45보다 큽니다.");
            }
            else
            {
                Debug.LogFormat("45보다 작습니다.");
                if (_isOn)
                {   
                    _hoverType = HoverType.OFF;    
                }
                else
                {
                    _hoverType = HoverType.ON;
                    _affordance.returnToInitialPosition = false;

                
                }
            }
            //EditorApplication.isPaused = true;
            
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (_isOn == false)
            {
                _affordance.returnToInitialPosition = true;
                _boxCollider.center = initBoxColliderCenter;
                _hoverType = HoverType.NONE;
            }
        });
        
    }

    private void Update()
    {
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                _isOn = true;
                Debug.Log("On");
            }
            else if(_hoverType == HoverType.OFF)
            {
                _isOn = false;
                Debug.Log("Off");
                _hoverType = HoverType.NONE;
            }
        }
    }
}

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    private Vector3 previousPosition;
    [SerializeField] private Transform attachTransform;
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        // 초기 위치 설정
        previousPosition = attachTransform.position;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;
            
            
            // 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
            Debug.LogFormat("previousPosition: {0}", previousPosition);
            Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
            Vector3 direction = previousPosition - poke.attachTransform.position;// - previousPosition;
            
            var ray = new Ray(poke.attachTransform.position, direction);
            //Debug.DrawRay(ray.origin, ray.direction, Color.red, 5f);
            DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);
            
            var dot = Vector3.Dot(poke.attachTransform.forward, -_boxCollider.transform.up);
            //Debug.LogFormat("{0}", dot);
                
            var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
            Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

            // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
            var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

            Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
            if (angle > 45)
            {
                Debug.LogFormat("45보다 큽니다.");
            }
            else
            {
                Debug.LogFormat("45보다 작습니다.");
                if (_isOn)
                {   
                    _hoverType = HoverType.OFF;    
                }
                else
                {
                    _hoverType = HoverType.ON;
                    _affordance.returnToInitialPosition = false;

                
                }
            }
            EditorApplication.isPaused = true;
            // 다시 이전 위치를 현재 위치로 업데이트
            //previousPosition = transform.position;
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (_isOn == false)
            {
                _affordance.returnToInitialPosition = true;
                _boxCollider.center = initBoxColliderCenter;
                _hoverType = HoverType.NONE;
            }
        });
        
    }

    private void Update()
    {
        // 매 프레임마다 현재 위치를 업데이트
        previousPosition = transform.position;
        
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                _isOn = true;
                Debug.Log("On");
            }
            else if(_hoverType == HoverType.OFF)
            {
                _isOn = false;
                Debug.Log("Off");
                _hoverType = HoverType.NONE;
            }
        }
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    private Vector3 previousPosition;
    [SerializeField] private Transform attachTransform;
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        // 초기 위치 설정
        previousPosition = attachTransform.position;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;
            
            
            // 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
            Debug.LogFormat("previousPosition: {0}", previousPosition);
            Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
            Vector3 direction = (previousPosition - poke.attachTransform.position).normalized;// - previousPosition;
            
            var ray = new Ray(_boxCollider.transform.position, direction);
            //Debug.DrawRay(ray.origin, ray.direction, Color.red, 5f);
            DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);
            
            var dot = Vector3.Dot(direction, -_boxCollider.transform.up);
            //Debug.LogFormat("{0}", dot);
                
            var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
            Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

            // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
            var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

            Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
            if (angle > 45)
            {
                Debug.LogFormat("45보다 큽니다.");
            }
            else
            {
                Debug.LogFormat("45보다 작습니다.");
                if (_isOn)
                {   
                    _hoverType = HoverType.OFF;    
                }
                else
                {
                    _hoverType = HoverType.ON;
                    _affordance.returnToInitialPosition = false;

                
                }
            }
            //EditorApplication.isPaused = true;
            
            // 다시 이전 위치를 현재 위치로 업데이트
            previousPosition = transform.position;
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (_isOn == false)
            {
                _affordance.returnToInitialPosition = true;
                _boxCollider.center = initBoxColliderCenter;
                _hoverType = HoverType.NONE;
            }
        });
        
    }

    private void Update()
    {
        // 매 프레임마다 현재 위치를 업데이트
        previousPosition = transform.position;
        
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                _isOn = true;
                Debug.Log("On");
            }
            else if(_hoverType == HoverType.OFF)
            {
                _isOn = false;
                Debug.Log("Off");
                _hoverType = HoverType.NONE;
            }
        }
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    private Vector3 previousPosition;
    [SerializeField] private Transform attachTransform;


    private bool isHoverEntered = false;
    
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        // 초기 위치 설정
        previousPosition = attachTransform.position;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;

            if (isHoverEntered == false)
            {
                isHoverEntered = true;
                if (_hoverType == HoverType.NONE)
                {
                    // 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
                    Debug.LogFormat("previousPosition: {0}", previousPosition);
                    Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
                    Vector3 direction = (previousPosition - poke.attachTransform.position).normalized;// - previousPosition;
            
                    var ray = new Ray(_boxCollider.transform.position, direction);
                    //Debug.DrawRay(ray.origin, ray.direction, Color.red, 5f);
                    DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);
            
                    var dot = Vector3.Dot(direction, -_boxCollider.transform.up);
                    //Debug.LogFormat("{0}", dot);
                
                    var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
                    Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

                    // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
                    var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

                    Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
                    if (angle > 45)
                    {
                        Debug.LogFormat("45보다 큽니다.");
                    }
                    else
                    {
                        Debug.LogFormat("45보다 작습니다.");
                        if (_isOn)
                        {   
                            _hoverType = HoverType.OFF;    
                        }
                        else
                        {
                            _hoverType = HoverType.ON;
                            _affordance.returnToInitialPosition = false;

                
                        }
                    }
                    //EditorApplication.isPaused = true;
            
                    // 다시 이전 위치를 현재 위치로 업데이트
                    previousPosition = transform.position;
                }
            }

            

           
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (_isOn == false)
            {
                _affordance.returnToInitialPosition = true;
                _boxCollider.center = initBoxColliderCenter;
            }
            
            _hoverType = HoverType.NONE;
            isHoverEntered = false;
        });
        
    }

    private void Update()
    {
        // 매 프레임마다 현재 위치를 업데이트
        previousPosition = transform.position;
        
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                if (_isOn == false)
                {
                    _isOn = true;
                    Debug.Log("On");
                }
            }
            else if(_hoverType == HoverType.OFF)
            {
                if (_isOn == true)
                {
                    _isOn = false;
                    Debug.Log("Off");
                    _hoverType = HoverType.NONE;
                }
            }
        }
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    private Vector3 previousPosition;
    [SerializeField] private Transform attachTransform;
    private bool isHoverEntered = false;
    private bool isValidated = false;
    
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        // 초기 위치 설정
        previousPosition = attachTransform.position;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;

            if (isHoverEntered == false)
            {
                isHoverEntered = true;
                if (_hoverType == HoverType.NONE)
                {
                    // 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
                    Debug.LogFormat("previousPosition: {0}", previousPosition);
                    Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
                    Vector3 direction = (previousPosition - poke.attachTransform.position).normalized;// - previousPosition;
            
                    var ray = new Ray(_boxCollider.transform.position, direction);
                    //Debug.DrawRay(ray.origin, ray.direction, Color.red, 5f);
                    DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);
            
                    var dot = Vector3.Dot(direction, -_boxCollider.transform.up);
                    //Debug.LogFormat("{0}", dot);
                
                    var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
                    Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

                    // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
                    var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

                    Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
                    if (angle > 45)
                    {
                        Debug.LogFormat("45보다 큽니다.");
                        _affordance.enabled = false;
                        isValidated = false;
                    }
                    else
                    {
                        Debug.LogFormat("45보다 작습니다.");
                        _affordance.enabled = true;
                        if (_isOn)
                        {   
                            _hoverType = HoverType.OFF;    
                        }
                        else
                        {
                            _hoverType = HoverType.ON;
                            _affordance.returnToInitialPosition = false;
                        }

                        isValidated = true;
                    }
                    //EditorApplication.isPaused = true;
            
                    // 다시 이전 위치를 현재 위치로 업데이트
                    previousPosition = transform.position;
                }
            }

            

           
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (isHoverEntered)
            {
                Debug.LogFormat("{0}, {1}", isValidated, _isOn);
                
                if (isValidated)
                {
                    if (_isOn == false)
                    {
                        _affordance.returnToInitialPosition = true;
                        _boxCollider.center = initBoxColliderCenter;
                    }    
                }
            
                _hoverType = HoverType.NONE;
                isHoverEntered = false;
                isValidated = false;
            }

            
        });
        
    }

    private void Update()
    {
        // 매 프레임마다 현재 위치를 업데이트
        previousPosition = transform.position;

        if (isValidated == false) return;
        
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                if (_isOn == false)
                {
                    _isOn = true;
                    Debug.Log("On");
                }
            }
            else if(_hoverType == HoverType.OFF)
            {
                if (_isOn == true)
                {
                    _isOn = false;
                    Debug.Log("Off");
                    _hoverType = HoverType.NONE;
                }
            }
        }
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
public enum HoverType
{
NONE, ON, OFF
}
private XRSimpleInteractable _interactable;
private XRPokeFollowAffordance _affordance;
private BoxCollider _boxCollider;
private Vector3 initBoxColliderCenter;
private HoverType _hoverType;
private bool _isOn;
private Vector3 previousPosition;
[SerializeField] private Transform attachTransform;
private bool isHoverEntered = false;
private bool isValidated = false;

void Start()
{
_interactable = GetComponent<XRSimpleInteractable>();
_affordance = GetComponent<XRPokeFollowAffordance>();
_boxCollider = GetComponent<BoxCollider>();

initBoxColliderCenter = _boxCollider.center;
// 초기 위치 설정
previousPosition = attachTransform.position;

_interactable.hoverEntered.AddListener(arg0 =>
{
var poke = arg0.interactorObject as XRPokeInteractor;

if (isHoverEntered == false)
{
isHoverEntered = true;
if (_hoverType == HoverType.NONE)
{
// 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
Debug.LogFormat("previousPosition: {0}", previousPosition);
Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
Vector3 direction = (previousPosition - poke.attachTransform.position).normalized;// - previousPosition;

var ray = new Ray(_boxCollider.transform.position, direction);
Debug.DrawRay(ray.origin, ray.direction, Color.red, 0.1f);
//DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);

var dot = Vector3.Dot(direction, -_boxCollider.transform.up);
//Debug.LogFormat("{0}", dot);

var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

// 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);

if (angle > 45)
{
Debug.LogFormat("45보다 큽니다.");
_affordance.enabled = false;
isValidated = false;
}
else
{
Debug.LogFormat("45보다 작습니다.");
_affordance.enabled = true;
if (_isOn)
{
_hoverType = HoverType.OFF;
}
else
{
_hoverType = HoverType.ON;
_affordance.returnToInitialPosition = false;
}

isValidated = true;
}
//EditorApplication.isPaused = true;

// 다시 이전 위치를 현재 위치로 업데이트
previousPosition = transform.position;
}
}




});

_interactable.hoverExited.AddListener((arg0) =>
{
if (isHoverEntered)
{
Debug.LogFormat("{0}, {1}", isValidated, _isOn);

if (isValidated)
{
if (_isOn == false)
{
_affordance.returnToInitialPosition = true;
_boxCollider.center = initBoxColliderCenter;
}
}

_hoverType = HoverType.NONE;
isHoverEntered = false;
isValidated = false;
}


});

}

private void Update()
{
// 매 프레임마다 현재 위치를 업데이트
previousPosition = transform.position;

if (isValidated == false) return;

if (_interactable.isHovered && _isOn == false)
{
//-0.045+0.0398
_boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
}

if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
{
if (_hoverType == HoverType.ON)
{
if (_isOn == false)
{
_isOn = true;
Debug.Log("On");
}
}
else if(_hoverType == HoverType.OFF)
{
if (_isOn == true)
{
_isOn = false;
Debug.Log("Off");
_hoverType = HoverType.NONE;
}
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    private Vector3 previousPosition;
    [SerializeField] private Transform attachTransform;
    private bool isHoverEntered = false;
    private bool isValidated = false;
    
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        // 초기 위치 설정
        previousPosition = attachTransform.position;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;

            if (isHoverEntered == false)
            {
                isHoverEntered = true;
                if (_hoverType == HoverType.NONE)
                {
                    // 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
                    Debug.LogFormat("previousPosition: {0}", previousPosition);
                    Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
                    Vector3 direction = (previousPosition - poke.attachTransform.position).normalized;// - previousPosition;
            
                    var ray = new Ray(_boxCollider.transform.position, direction);
                    Debug.DrawRay(ray.origin, ray.direction, Color.red, 0.1f);
                    //DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);
            
                    var dot = Vector3.Dot(direction, -_boxCollider.transform.up);
                    //Debug.LogFormat("{0}", dot);
                
                    var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
                    Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

                    // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
                    var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

                    Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
                    if (angle > 45)
                    {
                        Debug.LogFormat("45보다 큽니다.");
                        _affordance.enabled = false;
                        isValidated = false;
                    }
                    else
                    {
                        Debug.LogFormat("45보다 작습니다.");
                        _affordance.enabled = true;
                        if (_isOn)
                        {   
                            _hoverType = HoverType.OFF;    
                        }
                        else
                        {
                            _hoverType = HoverType.ON;
                            _affordance.returnToInitialPosition = false;
                        }

                        isValidated = true;
                    }
                    //EditorApplication.isPaused = true;
            
                    // 다시 이전 위치를 현재 위치로 업데이트
                    previousPosition = transform.position;
                }
            }

            

           
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (isHoverEntered)
            {
                Debug.LogFormat("{0}, {1}", isValidated, _isOn);
                
                if (isValidated)
                {
                    if (_isOn == false)
                    {
                        _affordance.returnToInitialPosition = true;
                        _boxCollider.center = initBoxColliderCenter;
                    }    
                }
            
                _hoverType = HoverType.NONE;
                isHoverEntered = false;
                isValidated = false;
            }

            
        });
        
    }

    private void Update()
    {
        // 매 프레임마다 현재 위치를 업데이트
        previousPosition = transform.position;

        if (isValidated == false) return;
        
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                if (_isOn == false)
                {
                    _isOn = true;
                    Debug.Log("On");
                }
            }
            else if(_hoverType == HoverType.OFF)
            {
                if (_isOn == true)
                {
                    _isOn = false;
                    Debug.Log("Off");
                    _hoverType = HoverType.NONE;
                }
            }
        }
    }
}

 

using UnityEngine;
using System.Collections;
#if UNITY_EDITOR
using UnityEditor;
#endif
// adapted from http://wiki.unity3d.com/index.php/DrawArrow 


public enum ArrowType
{
  Default,
	Thin,
	Double,
	Triple,
	Solid,
	Fat,
	ThreeD,
}

public static class DrawArrow
{
	public static void ForGizmo(Vector3 pos, Vector3 direction, Color? color = null,  bool doubled = false, float arrowHeadLength = 0.2f, float arrowHeadAngle = 20.0f)
	{
		Gizmos.color = color ?? Color.white;

		//arrow shaft
		Gizmos.DrawRay(pos, direction);
 
		if (direction != Vector3.zero)
		{
			//arrow head
			Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180+arrowHeadAngle,0) * new Vector3(0,0,1);
			Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180-arrowHeadAngle,0) * new Vector3(0,0,1);
			Gizmos.DrawRay(pos + direction, right * arrowHeadLength);
			Gizmos.DrawRay(pos + direction, left * arrowHeadLength);
		}
	}
 
	public static void ForDebug(Vector3 pos, Vector3 direction, float duration = 0.5f, Color? color = null, ArrowType type = ArrowType.Default, float arrowHeadLength = 0.2f, float arrowHeadAngle = 30.0f, bool sceneCamFollows = false)
	{
		Color actualColor = color ?? Color.white;
		duration = duration/Time.timeScale;
		
		float width = 0.01f;

		Vector3 directlyRight = Vector3.zero;
		Vector3 directlyLeft = Vector3.zero;
		Vector3 directlyBack = Vector3.zero;
		Vector3 headRight = Vector3.zero;
		Vector3 headLeft = Vector3.zero;

		if (direction != Vector3.zero)
		{
			directlyRight = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180+90,0) * new Vector3(0,0,1);
			directlyLeft = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180-90,0) * new Vector3(0,0,1);
			directlyBack = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180,0) * new Vector3(0,0,1);
			headRight = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180+arrowHeadAngle,0) * new Vector3(0,0,1);
			headLeft = Quaternion.LookRotation(direction) * Quaternion.Euler(0,180-arrowHeadAngle,0) * new Vector3(0,0,1);
		}		

		//draw arrow head
		Debug.DrawRay(pos + direction, headRight * arrowHeadLength, actualColor, duration);
		Debug.DrawRay(pos + direction, headLeft * arrowHeadLength, actualColor, duration);
		
		switch (type) {
		case ArrowType.Default:
			Debug.DrawRay(pos, direction, actualColor, duration); //draw center line
			break;
		case ArrowType.Double:
			Debug.DrawRay(pos + directlyRight * width, direction * (1-width), actualColor, duration); //draw line slightly to right
			Debug.DrawRay(pos +  directlyLeft * width, direction * (1-width), actualColor, duration); //draw line slightly to left

			//draw second arrow head
			Debug.DrawRay(pos + directlyBack * width + direction, headRight * arrowHeadLength, actualColor, duration);
			Debug.DrawRay(pos + directlyBack * width + direction, headLeft * arrowHeadLength, actualColor, duration);
			
			break;
		case ArrowType.Triple:
			Debug.DrawRay(pos, direction, actualColor, duration); //draw center line
			Debug.DrawRay(pos + directlyRight * width, direction * (1-width), actualColor, duration); //draw line slightly to right
			Debug.DrawRay(pos +  directlyLeft * width, direction * (1-width), actualColor, duration); //draw line slightly to left
			break;
		case ArrowType.Fat:
			break;
		case ArrowType.Solid:
			int increments = 20;
			for (int i=0;i<increments;i++)
			{
				float displacement = Mathf.Lerp(-width, +width, i/(float)increments);
				//draw arrow body
				Debug.DrawRay(pos + directlyRight * displacement, direction, actualColor, duration); //draw line slightly to right
				Debug.DrawRay(pos +  directlyLeft * displacement, direction, actualColor, duration); //draw line slightly to left
				//draw arrow head
				Debug.DrawRay((pos + direction) + directlyRight * displacement, headRight * arrowHeadLength, actualColor, duration);
				Debug.DrawRay((pos + direction) + directlyRight * displacement, headLeft * arrowHeadLength, actualColor, duration);
			}
			break;
		case ArrowType.Thin:
			Debug.DrawRay(pos, direction, actualColor, duration); //draw center line
			break;
		case ArrowType.ThreeD:
			break;
		}

/*#if UNITY_EDITOR
    //snap the Scene view camera to a spot where it is looking directly at this arrow.
		if (sceneCamFollows)
			SceneViewCameraFollower.activateAt(pos + direction, duration, "_arrow");
#endif*/
	}

	public static void randomStar(Vector3 center, Color color)
	{
		//special: refuse to draw at 0,0.
		if (center == Vector3.zero) return;
			for(int i=0;i<2;i++)
				DrawArrow.ForGizmo(center, UnityEngine.Random.onUnitSphere * 1, color, false, 0.1f, 30.0f);
	}
	
	public static void comparePositions(Transform t1, Transform t2)
	{
		//direct from one to the other:
		ForDebug(t1.position, t2.position - t1.position);

		//direction
		//Vector3 moveDirection = (t2.position-t1.position).normalized;
	}
}

 

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
 
[ExecuteAlways]
public class DrawOnBoxCollider : MonoBehaviour
{
    public enum DrawStates
    {
        DrawCube,
        DrawWireCube
    }
 
 
    public Transform boxColliderToDrawOn;
    [Range(0f, 1f)]
    public float colorTransparency;
    public bool draw = false;
    public DrawStates drawStates;
 
    private BoxCollider boxCollider = null;
 
    // Start is called before the first frame update
    void Start()
    {
        if (boxColliderToDrawOn != null)
        {
            boxCollider = boxColliderToDrawOn.GetComponent<BoxCollider>();
        }
 
        drawStates = DrawStates.DrawCube;
    }
 
    // Update is called once per frame
    void Update()
    {
       
    }
 
    private void DrawGizmosOnRunTime(Color color)
    {
        if (boxCollider != null && draw)
        {
            Gizmos.color = color;
            Matrix4x4 rotationMatrix = Matrix4x4.TRS(boxCollider.transform.position, boxCollider.transform.rotation, boxCollider.transform.lossyScale);
            Gizmos.matrix = rotationMatrix;
 
            switch (drawStates)
            {
                case DrawStates.DrawCube:
                    Gizmos.DrawCube(boxCollider.center, boxCollider.size);
                    break;
 
                case DrawStates.DrawWireCube:
                    Gizmos.DrawWireCube(boxCollider.center, boxCollider.size);
                    break;
            }
        }
    }
 
    private void OnDrawGizmos()
    {
        Color c = Color.red;
        c.a = colorTransparency;
        DrawGizmosOnRunTime(c);
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PushButtonController : MonoBehaviour
{
    public enum HoverType
    {
        NONE, ON, OFF
    }
    private XRSimpleInteractable _interactable;
    private XRPokeFollowAffordance _affordance;
    private BoxCollider _boxCollider;
    private Vector3 initBoxColliderCenter;
    private HoverType _hoverType;
    private bool _isOn;
    private Vector3 previousPosition;
    [SerializeField] private Transform attachTransform;
    private bool isHoverEntered = false;
    private bool isValidated = false;
    
    void Start()
    {
        _interactable = GetComponent<XRSimpleInteractable>();
        _affordance = GetComponent<XRPokeFollowAffordance>();
        _boxCollider = GetComponent<BoxCollider>();
        
        initBoxColliderCenter = _boxCollider.center;
        // 초기 위치 설정
        previousPosition = attachTransform.position;
        
        _interactable.hoverEntered.AddListener(arg0 =>
        {
            var poke = arg0.interactorObject as XRPokeInteractor;

            if (isHoverEntered == false)
            {
                isHoverEntered = true;
                if (_hoverType == HoverType.NONE)
                {
                    // 콜리전 발생 시 이전 위치와 현재 위치를 비교하여 이동 방향 계산
                    Debug.LogFormat("previousPosition: {0}", previousPosition);
                    Debug.LogFormat("poke.attachTransform.position: {0}", poke.attachTransform.position);
                    Vector3 direction = (previousPosition - poke.attachTransform.position).normalized;// - previousPosition;
            
                    var ray = new Ray(_boxCollider.transform.position, direction);
                    Debug.DrawRay(ray.origin, ray.direction, Color.red, 0.1f);
                    //DrawArrow.ForDebug(ray.origin, ray.direction, 5f, Color.red, ArrowType.Solid);
            
                    var dot = Vector3.Dot(direction, -_boxCollider.transform.up);
                    //Debug.LogFormat("{0}", dot);
                
                    var ray2 = new Ray(_boxCollider.transform.position, -_boxCollider.transform.up);
                    Debug.DrawRay(ray2.origin, ray2.direction, Color.green, 5f);

                    // 코사인 값으로부터 각도(라디안)를 계산한 후, 라디안을 도로 변환
                    var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

                    Debug.LogFormat("Dot: {0}, Angle: {1} degrees", dot, angle);
                
                    if (angle > 45)
                    {
                        Debug.LogFormat("45보다 큽니다.");
                        _affordance.enabled = false;
                        isValidated = false;
                    }
                    else
                    {
                        Debug.LogFormat("45보다 작습니다.");
                        _affordance.enabled = true;
                        if (_isOn)
                        {   
                            _hoverType = HoverType.OFF;    
                        }
                        else
                        {
                            _hoverType = HoverType.ON;
                            _affordance.returnToInitialPosition = false;
                        }

                        isValidated = true;
                    }
                    //EditorApplication.isPaused = true;
            
                    // 다시 이전 위치를 현재 위치로 업데이트
                    previousPosition = transform.position;
                }
            }

            

           
        });
        
        _interactable.hoverExited.AddListener((arg0) =>
        {
            if (isHoverEntered)
            {
                Debug.LogFormat("{0}, {1}", isValidated, _isOn);
                
                if (isValidated)
                {
                    if (_isOn == false)
                    {
                        _affordance.returnToInitialPosition = true;
                        _boxCollider.center = initBoxColliderCenter;
                    }    
                }
            
                _hoverType = HoverType.NONE;
                isHoverEntered = false;
                isValidated = false;
            }

            
        });
        
    }

    private void Update()
    {
        // 매 프레임마다 현재 위치를 업데이트
        previousPosition = transform.position;

        if (isValidated == false) return;
        
        if (_interactable.isHovered && _isOn == false)
        {
            //-0.045+0.0398
            _boxCollider.center = new Vector3(0, -0.045f + _affordance.pokeFollowTransform.localPosition.y, 0);
        }

        if (_interactable.isHovered && _affordance.pokeFollowTransform.localPosition == Vector3.zero)
        {
            if (_hoverType == HoverType.ON)
            {
                if (_isOn == false)
                {
                    _isOn = true;
                    Debug.Log("On");
                }
            }
            else if(_hoverType == HoverType.OFF)
            {
                if (_isOn == true)
                {
                    _isOn = false;
                    Debug.Log("Off");
                    _hoverType = HoverType.NONE;
                }
            }
        }
    }
}
반응형
: