【Unity(C#)】Oculus Integration으로 손의 머티리얼 전환

데모



바로 데모입니다.


물체를 건드리면 손의 재질이 건드린 물체와 같은 것으로 바뀝니다.

이 정보만으로 코드가 머리 속에 완성되어 버리는 사람도 적지 않을까 생각합니다만,
왠지, 원하는 결과를 얻을 수 없어 원인 특정에 시간을 필요로 했으므로 메모해 둡니다.

원하는 결과를 얻지 못한 코드



터치되는 물체 측에 부착
public class HandTriggerEnterEvent : MonoBehaviour
{
    private MeshRenderer _meshRenderer;

    private void Start()
    { 
        _mshRenderer = this.gameObject.GetComponent<MeshRenderer>();
    }

    private void OnTriggerEnter(Collider other)
    {
        //この書き方については今回の本題ではないのでスルー安定
        SkinnedMeshRenderer skinnedMeshRenderer = other.gameObject.transform.parent.parent.parent.GetComponent<SkinnedMeshRenderer>();

        if (skinnedMeshRenderer != null)
        {
            Debug.Log("Get Color");

            //マテリアルを手に適用
            skinnedMeshRenderer.material = _meshRenderer.material;
        }
        else
        {
            Debug.Log("skinnedMeshRenderer is Null");
        }
    }
}

언뜻 보면 건드리면 머티리얼을 손에 반영
그냥 코드만으로 문제 없어 보이지만,
머티리얼은 변하지 않습니다.

원인



원인은 OVRHandPrefab 에 첨부된 OVRMeshRenderer Update의 코드에 있었습니다.
private void Update()
{
    IsDataValid = false;
    IsDataHighConfidence = false;
    ShouldUseSystemGestureMaterial = false;

    if (IsInitialized)
    {
        bool shouldRender = false;

        if (_dataProvider != null)
        {
            var data = _dataProvider.GetMeshRendererData();

            IsDataValid = data.IsDataValid;
            IsDataHighConfidence = data.IsDataHighConfidence;
            ShouldUseSystemGestureMaterial = data.ShouldUseSystemGestureMaterial;

            shouldRender = data.IsDataValid && data.IsDataHighConfidence;
        }

        if (_confidenceBehavior == ConfidenceBehavior.ToggleRenderer)
        {
            if (_skinnedMeshRenderer != null && _skinnedMeshRenderer.enabled != shouldRender)
            {
                _skinnedMeshRenderer.enabled = shouldRender;
            }
        }

        if (_systemGestureBehavior == SystemGestureBehavior.SwapMaterial)
        {
            if (_skinnedMeshRenderer != null)
            {
                if (ShouldUseSystemGestureMaterial && _systemGestureMaterial != null && _skinnedMeshRenderer.sharedMaterial != _systemGestureMaterial)
                {
                    _skinnedMeshRenderer.sharedMaterial = _systemGestureMaterial;
                }
                else if (!ShouldUseSystemGestureMaterial && _originalMaterial != null && _skinnedMeshRenderer.sharedMaterial != _originalMaterial)
                {
                    _skinnedMeshRenderer.sharedMaterial = _originalMaterial;
                }
            }
        }
    }
#if UNITY_EDITOR
    else
    {
        if (OVRInput.IsControllerConnected(OVRInput.Controller.Hands))
        {
            Initialize();
        }
    }
#endif
}

SystemGestureBehavior.SwapMaterial라는 상태로 설정하면,
머티리얼이 변경되자마자 _originalMaterial로 돌아갑니다.

그래서 Inspector에서 디폴트 설정되어 있는 System Gesture BehaviorSwapMaterialNone 로 변경하면 OK였습니다.



여담이지만 Confidence Behavior기본적으로 Toggle Renderer로 설정된 매개 변수로,
손 추적 상황에 따라 Renderer를 켜고 끌 수 있습니다.

SystemGestureBehavior


System Gesture Behavior는 OculusQuest의 핸드 트래킹 기능에
기본적으로 제공됨
"홈 화면으로 돌아가는 제스처의 예비 동작(손바닥을 자신을 향한다)"에 관련된 기능입니다.
SwapMaterial를 설정하면,
"홈 화면으로 돌아가는 제스처의 예비 동작 (손바닥을 자신에게 향한다)"을 실시하면
손 머티리얼이 System Gesture Material 로 설정된 머티리얼로 변경됩니다.


만약, 이 System Gesture BehaviorSwapMaterial 도 이용하면서
다른 머티리얼과의 교체도 구현하고 싶은 경우,
아래와 같이 조금 코드를 다시 작성해야합니다.

OVRMeshRenderer Update의 코드
if (_systemGestureBehavior == SystemGestureBehavior.SwapMaterial)
{
    if (_skinnedMeshRenderer != null)
    {
        if (ShouldUseSystemGestureMaterial && _systemGestureMaterial != null && _skinnedMeshRenderer.sharedMaterial != _systemGestureMaterial)
        {
            Debug.Log("Get Current Material");
            _originalMaterial = GetComponent<SkinnedMeshRenderer>().sharedMaterial;
            _skinnedMeshRenderer.sharedMaterial = _systemGestureMaterial;
        }
        else if (!ShouldUseSystemGestureMaterial && _originalMaterial != null && _skinnedMeshRenderer.sharedMaterial == _systemGestureMaterial)
        {
            _skinnedMeshRenderer.sharedMaterial = _originalMaterial;
        }
    }
}

참고 링크



SkinnedMeshRenderer material from OVRHand prefab is overwritten every frame

좋은 웹페이지 즐겨찾기