412 lines
15 KiB
C#
412 lines
15 KiB
C#
/*
|
|
* ExternalReceiver
|
|
* https://sabowl.sakura.ne.jp/gpsnmeajp/
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2019 gpsnmeajp
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace EVMC4U
|
|
{
|
|
[RequireComponent(typeof(ExternalReceiver))]
|
|
public class HandCatch : MonoBehaviour
|
|
{
|
|
//表示オンオフ
|
|
public bool ShowCollider = true;
|
|
bool ShowColliderOld = true;
|
|
|
|
public float NonHoldFilter = 0f;
|
|
public float InHoldFilter = 0.90f;
|
|
|
|
float offset = 0.06f;
|
|
float size = 0.15f;
|
|
|
|
public string CollisionTag = "";
|
|
|
|
public float SpeedMultiplier = 1.0f;
|
|
|
|
public string LeftKey = "Z";
|
|
public string RightKey = "X";
|
|
public string ControllerButton = "ClickTrigger";
|
|
|
|
public bool signaling = true;
|
|
|
|
public bool StickyMode = false;
|
|
|
|
bool stickyLeft = false;
|
|
bool stickyRight = false;
|
|
|
|
ExternalReceiver exrcv;
|
|
InputReceiver inputrcv;
|
|
|
|
Transform leftHand;
|
|
Transform rightHand;
|
|
|
|
GameObject leftSphere;
|
|
GameObject rightSphere;
|
|
|
|
Rigidbody leftRigidBody;
|
|
Rigidbody rightRigidBody;
|
|
|
|
Vector3 leftLastPos;
|
|
Vector3 rightLastPos;
|
|
Vector3 leftLastSpeed;
|
|
Vector3 rightLastSpeed;
|
|
|
|
HandCatch_Helper leftHelper;
|
|
HandCatch_Helper rightHelper;
|
|
|
|
GameObject leftCatchedObject;
|
|
GameObject rightCatchedObject;
|
|
|
|
bool leftCatchedObjectIsKinematic;
|
|
bool rightCatchedObjectIsKinematic;
|
|
|
|
Transform leftCatchedObjectParent;
|
|
Transform rightCatchedObjectParent;
|
|
|
|
void Start()
|
|
{
|
|
//ExternalReceiverにキー操作を登録
|
|
exrcv = GetComponent<EVMC4U.ExternalReceiver>();
|
|
inputrcv = GetComponentInChildren<EVMC4U.InputReceiver>();
|
|
|
|
inputrcv.ControllerInputAction.AddListener(ControllerInputEvent);
|
|
inputrcv.KeyInputAction.AddListener(KeyInputEvent);
|
|
|
|
//ブレ防止用にフィルタを設定
|
|
exrcv.BonePositionFilterEnable = true;
|
|
exrcv.BoneRotationFilterEnable = true;
|
|
exrcv.BoneFilter = NonHoldFilter;
|
|
|
|
//手のボーンを取得
|
|
var anim = exrcv.Model.GetComponent<Animator>();
|
|
leftHand = anim.GetBoneTransform(HumanBodyBones.LeftHand);
|
|
rightHand = anim.GetBoneTransform(HumanBodyBones.RightHand);
|
|
|
|
//左手当たり判定スフィア生成
|
|
leftSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
leftSphere.transform.parent = leftHand;
|
|
leftSphere.transform.localPosition = new Vector3(-offset, 0f, 0f);
|
|
leftSphere.transform.localScale = new Vector3(size, size, size);
|
|
|
|
//左手当たり判定スフィアコライダー設定
|
|
var leftCollider = leftSphere.GetComponent<Collider>();
|
|
//コライダーは反応のみで衝突しない
|
|
leftCollider.isTrigger = true;
|
|
|
|
//左手当たり判定物理演算追加
|
|
leftRigidBody = leftSphere.AddComponent<Rigidbody>();
|
|
//物理は反応のみで演算しない
|
|
leftRigidBody.isKinematic = true;
|
|
|
|
//左手当たり判定ヘルパー追加
|
|
leftHelper = leftSphere.AddComponent<HandCatch_Helper>();
|
|
|
|
//右手当たり判定スフィア生成
|
|
rightSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
rightSphere.transform.parent = rightHand;
|
|
rightSphere.transform.localPosition = new Vector3(offset, 0f, 0f);
|
|
rightSphere.transform.localScale = new Vector3(size, size, size);
|
|
|
|
//右手当たり判定スフィアコライダー設定
|
|
var rightCollider = rightSphere.GetComponent<Collider>();
|
|
//コライダーは反応のみで衝突しない
|
|
rightCollider.isTrigger = true;
|
|
|
|
//右手当たり判定物理演算追加
|
|
rightRigidBody = rightSphere.AddComponent<Rigidbody>();
|
|
//物理は反応のみで演算しない
|
|
rightRigidBody.isKinematic = true;
|
|
|
|
//右手当たり判定ヘルパー追加
|
|
rightHelper = rightSphere.AddComponent<HandCatch_Helper>();
|
|
}
|
|
|
|
//物理演算のためFixedUpdate
|
|
void FixedUpdate()
|
|
{
|
|
//剥がれ防止で親を設定
|
|
leftSphere.transform.parent = leftHand;
|
|
leftSphere.transform.localPosition = new Vector3(-offset, 0f, 0f);
|
|
leftSphere.transform.localScale = new Vector3(size, size, size);
|
|
rightSphere.transform.parent = rightHand;
|
|
rightSphere.transform.localPosition = new Vector3(offset, 0f, 0f);
|
|
rightSphere.transform.localScale = new Vector3(size, size, size);
|
|
|
|
//表示非表示を反映
|
|
if (ShowColliderOld != ShowCollider) {
|
|
leftSphere.GetComponent<MeshRenderer>().enabled = ShowCollider;
|
|
rightSphere.GetComponent<MeshRenderer>().enabled = ShowCollider;
|
|
|
|
ShowColliderOld = ShowCollider;
|
|
}
|
|
|
|
//投げるとき用にフレーム間速度を求める
|
|
leftLastSpeed = SpeedMultiplier * (leftHand.transform.position - leftLastPos)/Time.fixedDeltaTime;
|
|
leftLastPos = leftHand.transform.position;
|
|
rightLastSpeed = SpeedMultiplier * (rightHand.transform.position - rightLastPos)/Time.fixedDeltaTime;
|
|
rightLastPos = rightHand.transform.position;
|
|
}
|
|
|
|
//左手掴む処理
|
|
void CatchLeft(bool s)
|
|
{
|
|
if (s)
|
|
{
|
|
//つかみ処理
|
|
if (leftHelper.Trigger && leftHelper.other != null)
|
|
{
|
|
//コリジョンタグになにか文字が入っていて、対象と一致しない場合は処理しない
|
|
if (CollisionTag != "" && CollisionTag != leftHelper.other.tag) {
|
|
return;
|
|
}
|
|
//左手ですでに掴んでいるものは掴まない
|
|
if (leftHelper.other.gameObject.transform.parent == leftSphere.transform)
|
|
{
|
|
return;
|
|
}
|
|
//右手ですでに掴んでいるものは掴まない
|
|
if (leftHelper.other.gameObject.transform.parent == rightSphere.transform)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//解除用に保持
|
|
leftCatchedObject = leftHelper.other.gameObject;
|
|
|
|
//親を保存
|
|
leftCatchedObjectParent = leftCatchedObject.transform.parent;
|
|
|
|
//手を親に上書き
|
|
leftCatchedObject.transform.parent = leftSphere.transform;
|
|
|
|
//掴むために物理演算を切る
|
|
var rigid = leftCatchedObject.GetComponent<Rigidbody>();
|
|
if (rigid != null) {
|
|
//IsKinematicを保存
|
|
leftCatchedObjectIsKinematic = rigid.isKinematic;
|
|
//設定に関わらずtrueにする
|
|
rigid.isKinematic = true;
|
|
}
|
|
|
|
//フィルタ強く
|
|
exrcv.BoneFilter = InHoldFilter;
|
|
|
|
//オブジェクトにメッセージを送る
|
|
if (signaling)
|
|
{
|
|
leftCatchedObject.SendMessage("OnCatchedLeftHand");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (leftCatchedObject != null)
|
|
{
|
|
//解除して親に戻す
|
|
leftCatchedObject.transform.parent = leftCatchedObjectParent;
|
|
|
|
//掴むために物理演算を切る
|
|
var rigid = leftCatchedObject.GetComponent<Rigidbody>();
|
|
if (rigid != null)
|
|
{
|
|
//IsKinematicを保存していた設定にする
|
|
rigid.isKinematic = leftCatchedObjectIsKinematic;
|
|
|
|
//投げるために速度を転送する
|
|
rigid.linearVelocity = leftLastSpeed;
|
|
}
|
|
|
|
//フィルタ解除
|
|
exrcv.BoneFilter = NonHoldFilter;
|
|
|
|
//オブジェクトにメッセージを送る
|
|
if (signaling)
|
|
{
|
|
leftCatchedObject.SendMessage("OnReleasedLeftHand");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CatchRight(bool s)
|
|
{
|
|
if (s)
|
|
{
|
|
if (rightHelper.Trigger && rightHelper.other != null)
|
|
{
|
|
//コリジョンタグになにか文字が入っていて、対象と一致しない場合は処理しない
|
|
if (CollisionTag != "" && CollisionTag != rightHelper.other.tag)
|
|
{
|
|
return;
|
|
}
|
|
//左手ですでに掴んでいるものは掴まない
|
|
if (rightHelper.other.gameObject.transform.parent == leftSphere.transform)
|
|
{
|
|
return;
|
|
}
|
|
//右手ですでに掴んでいるものは掴まない
|
|
if (rightHelper.other.gameObject.transform.parent == rightSphere.transform)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//解除用に保持
|
|
rightCatchedObject = rightHelper.other.gameObject;
|
|
|
|
//親を保存
|
|
rightCatchedObjectParent = rightCatchedObject.transform.parent;
|
|
|
|
//手を親に上書き
|
|
rightCatchedObject.transform.parent = rightSphere.transform;
|
|
|
|
//掴むために物理演算を切る
|
|
var rigid = rightCatchedObject.GetComponent<Rigidbody>();
|
|
if (rigid != null)
|
|
{
|
|
//IsKinematicを保存
|
|
rightCatchedObjectIsKinematic = rigid.isKinematic;
|
|
//設定に関わらずtrueにする
|
|
rigid.isKinematic = true;
|
|
}
|
|
|
|
//フィルタ強く
|
|
exrcv.BoneFilter = InHoldFilter;
|
|
|
|
//オブジェクトにメッセージを送る
|
|
if (signaling)
|
|
{
|
|
rightCatchedObject.SendMessage("OnCatchedRightHand");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rightCatchedObject != null)
|
|
{
|
|
//解除して親に戻す
|
|
rightCatchedObject.transform.parent = rightCatchedObjectParent;
|
|
|
|
//掴むために物理演算を切る
|
|
var rigid = rightCatchedObject.GetComponent<Rigidbody>();
|
|
if (rigid != null)
|
|
{
|
|
//IsKinematicを保存していた設定にする
|
|
rigid.isKinematic = rightCatchedObjectIsKinematic;
|
|
|
|
Debug.Log(rightRigidBody.linearVelocity);
|
|
//投げるために速度を転送する
|
|
rigid.linearVelocity = rightLastSpeed;
|
|
}
|
|
|
|
//フィルタ解除
|
|
exrcv.BoneFilter = NonHoldFilter;
|
|
|
|
//オブジェクトにメッセージを送る
|
|
if (signaling)
|
|
{
|
|
rightCatchedObject.SendMessage("OnReleasedRightHand");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void KeyInputEvent(EVMC4U.KeyInput key)
|
|
{
|
|
if (!StickyMode)
|
|
{
|
|
//Zキーが押されたか
|
|
if (key.name == LeftKey)
|
|
{
|
|
//つかみ・離し
|
|
CatchLeft(key.active == 1);
|
|
}
|
|
//Xキー押されたか
|
|
if (key.name == RightKey)
|
|
{
|
|
//つかみ・離し
|
|
CatchRight(key.active == 1);
|
|
}
|
|
}
|
|
else {
|
|
if (key.active == 1)
|
|
{
|
|
//Zキーが押されたか
|
|
if (key.name == LeftKey)
|
|
{
|
|
//つかみ・離し
|
|
stickyLeft = !stickyLeft;
|
|
CatchLeft(stickyLeft);
|
|
}
|
|
//Xキー押されたか
|
|
if (key.name == RightKey)
|
|
{
|
|
//つかみ・離し
|
|
stickyRight = !stickyRight;
|
|
CatchRight(stickyRight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ControllerInputEvent(EVMC4U.ControllerInput con)
|
|
{
|
|
//トリガー引かれたか
|
|
if (con.name == ControllerButton)
|
|
{
|
|
if (!StickyMode)
|
|
{
|
|
if (con.IsLeft == 1)
|
|
{
|
|
//つかみ・離し
|
|
CatchLeft(con.active == 1);
|
|
}
|
|
else
|
|
{
|
|
//つかみ・離し
|
|
CatchRight(con.active == 1);
|
|
}
|
|
}
|
|
else {
|
|
if (con.active == 1) {
|
|
if (con.IsLeft == 1)
|
|
{
|
|
//つかみ・離し
|
|
stickyLeft = !stickyLeft;
|
|
CatchLeft(stickyLeft);
|
|
}
|
|
else
|
|
{
|
|
//つかみ・離し
|
|
stickyRight = !stickyRight;
|
|
CatchRight(stickyRight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |