実現したいこと
動いているボールオブジェクトを、キャッチ(setparentで親(プレイヤー)オブジェクトに紐づける)際に、位置ずれが発生するため、
これを解消したいです。
前提
UnityとPUN2でドッチボールのマルチプレイゲームを作成しています。
⓵プレイヤーが、止まっているボールを拾う
②別プレイヤーに向けて投げる
③プレイヤーがボールをキャッチする
ような基本的な処理を実装しているのですが、
③の処理において、
動いているボールオブジェクトを、キャッチ(setparentで親(プレイヤー)オブジェクトに紐づける)際に、
ボールが掌に収まらず、位置ずれが発生します。
該当のソースコード
キャッチするコードは以下になります
プレイヤーオブジェクトのスクリプト
// ボールを持つ private IEnumerator HoldBall(Collision collision) { // 衝突したボールオブジェクトのView取得 ballView = collision.collider.GetComponent<PhotonView>(); // ボールのVIEWが取得できない場合 if (ballView == null) { yield break; } // ルームプロパティを取得 var roomProperties = PhotonNetwork.CurrentRoom.CustomProperties; // ボール保持者がいない場合 if ((int)roomProperties["currentBallHolderViewID"] == -1) { // 新しいボール保持者のViewIDをルームプロパティに設定 roomProperties["currentBallHolderViewID"] = photonView.ViewID; PhotonNetwork.CurrentRoom.SetCustomProperties(roomProperties); } // ボール保持者がいる場合 else { Debug.LogWarning("ボールの保持者がいるため、ボールを所持できません"); yield break; } // ボールの所有権がない場合 if (!ballView.IsMine) { // ボールの所有権をリクエスト ballView.RequestOwnership(); Debug.Log("ボールの所有権をリクエストしました"); // 所有権が付与されるまで待つ yield return new WaitUntil(() => ballView.IsMine); } // ボールのRigidbodyを取得して停止 Rigidbody ballRb = ballView.GetComponent<Rigidbody>(); ballRb.velocity = Vector3.zero; // 速度をリセット ballRb.angularVelocity = Vector3.zero; // 回転速度をリセット ballRb.isKinematic = true; // 物理演算を無効にする // 全てのクライアントに親子関係の追加を通知 ballView.RPC("SetBallToPlayer", RpcTarget.AllViaServer, photonView.ViewID); // ボールを持っているパネルを表示 photonView.RPC("UpdatePanelVisibility", photonView.Owner, true); Debug.Log($"{PhotonNetwork.LocalPlayer.UserId} が、ボールを所持しました"); }
ボールオブジェクトのスクリプト
// RPCで他のクライアントに、ボールの親子関係の追加する [PunRPC] void SetBallToPlayer(int ballHolderViewId) { Debug.Log($"ViewID:{ballHolderViewId}にボールの親子関係を設定します"); // ボールのバウンドを無効 ballCol.material.bounciness = 0f; // 対象のプレイヤーのViewを取得 ballHolderView = PhotonView.Find(ballHolderViewId); if (ballHolderView == null) { Debug.LogError($"ViewID:{ballHolderViewId} のプレイヤーが見つかりません"); } // ボールと、ボールを持っているプレイヤーの衝突を無視する(rigidbodyを無効にしても、衝突によりプレイヤーが後ずさりしてしまうため) Collider ballHolderPlayerCol = ballHolderView.GetComponent<Collider>(); Physics.IgnoreCollision(ballCol, ballHolderPlayerCol, true); // 対象のプレイヤーの右手のボーンを見つける Transform rightHandBone = ballHolderView.transform.Find("mixamorig6:Hips/mixamorig6:Spine/mixamorig6:Spine1/mixamorig6:Spine2/mixamorig6:RightShoulder/mixamorig6:RightArm/mixamorig6:RightForeArm/mixamorig6:RightHand"); if (rightHandBone == null) { Debug.LogError("右手のボーンが見つかりません"); } // 右手のボーン>ボールの親子関係を設定(ワールド座標保持) transform.SetParent(rightHandBone, true); }
位置ずれ以外は正常に動作してます。
プレイヤーやボールのオブジェクト位置の同期には
photonTransfromViewを使用しています。
試したこと
setparentの第二引数はfalse(ローカル座標)にする
// 右手のボーン>ボールの親子関係を設定(ワールド座標保持) transform.SetParent(rightHandBone, true);
の部分について、
当初、setparentの第二引数はfalse(ローカル座標)
にしていました。
その場合、
⓵プレイヤーが、止まっているボールを拾うの時には、
手のひらにボールがきっちり収まるのですが、
③プレイヤーがボールをキャッチする
の際の位置ずれが現在の5倍(肌感です)くらいになるため、
今は、true(ワールド座標保持)にしています。
setparentのあとに、transform.positionとrotationを補正する
GPTに聞くと、
setparentのあとに、transform.positionとrotationを明示的に補正するといいといわれたため、
試したのですが、
後続の②のボールを投げる処理にある
transform.SetParent(null, true)
が動かなくなった?ため、ダメでした。
RigidbodyのIntarpolate(位置補間)などは使用
ずれが大きくなっていくためダメでした
PhotonRigidbodyViewとの併用
効果なしでした。
補足情報(FW/ツールのバージョンなど)
Unity(2022.3.28f1)
PUN2
あなたの回答
tips
プレビュー