質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.21%

複雑なキャラクターの構造において、RigidbodyとColliderを共存させる方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 477

Harumaro

score 75

全体的な流れと原因

プレイヤーがColliderに侵入したら、別の場所へテレポートするというプログラムを作ろうと思いましたが、上手くいきませんでした。原因は一応わかっているのですが、解決方法がわかりませんでした。
原因はSAColliderBuilderというAssetのせいでした。

イメージ説明
まず、頭、首、体、右腕、左腕、右足、左足のように体を7つに分割しました(ゲームの性質上、7つに分割しなければいけません)
Prim.00000000は、MeshColliderをつけるためのオブジェクト(MeshColliderがアタッチされていました)で、Default-Materialはそれをまとめるためのオブジェクト?だと思われます。
この二つのオブジェクトはSAColliderBuilderによって、自動生成されます。
そして、そのオブジェクトをPlayerというオブジェクトでまとめ、Playerには以下のようなComponentをアタッチしています。
イメージ説明
Controllはプレイヤーを動かすためのスクリプトです。

そして別に、Is Triggerをオンにしたオブジェクトを作りそこのColliderへPlayerが侵入すると、別の場所へテレポートするという仕組みです。

また、Playerオブジェクト自体に別に適当なBoxColliderをアタッチしたところ、正常に動き、テレポートしました。
結論としては、RigidBodyとColliderが別々のオブジェクトにアタッチされていたのが原因でした。
※PlayerにRigidBodyが付いていて、Prim.00000000にMeshColliderが付いていてしまっているということです。

RigidBodyとColliderを同じオブジェクトにアタッチしたいのですが、自分の力ではどうしてもすることが出来ませんでした。
何か解決策を教えていただけるとありがたいです。

プレイヤーをテレポートさせる際に、プレイヤーの侵入を検知し、座標を変えるスクリプト

このスクリプトは、Is Triggerをオンにした球形のコライダーを作り、そこにアタッチしたものです。
また、テレポート先にTptoという名のオブジェクトがあり、プレイヤーの侵入を検知した際に、そのオブジェクトにプレイヤーの座標を設定するという仕組みになっています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class into1 : MonoBehaviour {
    public GameObject Player;
    public GameObject Tpto;
    // Start is called before the first frame update
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
    void OnTriggerEnter (Collider col1) {
        if (col1.CompareTag ("Player")) {
            Player.transform.position = Tpto.transform.position;
            Debug.Log ("true");
        }
    }
}

試したこと

・Playerの中のBodyなどの一部のオブジェクトにRigidbodyとスクリプトを移動させたがそもそも移動できなくなった。
・MeshColliderを一つにまとめて、Playerに付けちゃおうと思ったが、そもそも一つにまとめてしまうと、オブジェクトごとに当たり判定を消すことができなくなってしまうので断念。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Bongo

    2019/07/04 05:54

    ご提示ありがとうございます。もう2つ確認させていただきたいのですが、まず現状の構造だとテレポート領域に触れたときどのような現象が起こるのでしょうか(テレポートしない、OnTriggerEnterが発生しない、OnTriggerEnter自体は発生するがコンソールに「true」が出ない...つまり条件判定をクリアできない、など)。もう一つ、ご提示のスクリーンショットではPlayerに「Player」タグがついていますが、それ以下の階層(各部位、Default-Material、Prim.00000000)にも全部「Player」タグを付けていますでしょうか?

    キャンセル

  • Harumaro

    2019/07/04 06:18

    コンソールにtrueが表示されていなかったので、おそらくOnTriggerEnter自体動作していないと思います。
    そして、以下の階層にもPlayerタグをつける必要があったんですね...解決しましたw
    本当にありがとうございました!
    一応確認させていただきたいのですが、基本的に子要素にColliderもしくはRigidbodyが別れている場合、
    その子要素にもタグをつけないとColliderとRigidbodyの両方を検出できないため今回の場合、OnTriggerEnterが動作しなかったという認識でよろしいでしょうか?

    キャンセル

  • Harumaro

    2019/07/04 06:21

    あとぜひBongoさんの回答をベストアンサーにしたいので、回答欄に今回の解決策を書いていただきたいです。

    キャンセル

回答 1

checkベストアンサー

+1

解決されましたようで安心しました。お言葉に甘えまして回答欄にコメントさせていただきますと...

  1. プレイヤーの体のある部位がテレポート領域に触れる。
  2. テレポート領域のOnTriggerEnterが作動し、引数のcol1にはその部位のコライダーが渡される。
  3. たとえ一番上のプレイヤーオブジェクトに「Player」タグを付けていたとしても、今注目しているのはその部位のオブジェクトにアタッチされているコライダーなので(if (col1.CompareTag ("Player"))という風に、col1のタグが「Player」かどうかをチェックしている)、その部位に「Player」タグがついていないとif内に入らず、テレポートが発生しない。

という状況だった様子ですね。タグ設定はあくまでもそのオブジェクト自体にしか影響せず、子オブジェクトは親オブジェクトのタグ設定の影響を受けるわけではないため、このようなことになったものと考えられます。

OnTriggerEnter自体が発生していないのか、あるいは条件判定に失敗しているのかは、現状のコードですとコンソールに「true」が表示されるかどうかだけでは区別できないはずです。
区別するにはifの外にもなにかしらDebug.Logを入れて...

    void OnTriggerEnter (Collider col1) {
        Debug.Log("OnTriggerEnter"); // ここはOnTriggerEnterが発生しさえすれば実行される
        if (col1.CompareTag ("Player")) {
            Player.transform.position = Tpto.transform.position;
            Debug.Log ("true"); // ここはOnTriggerEnterが発生、かつ条件判定もクリアしないと実行されない
        }
    }

としてやる手があるでしょう。

  • 「OnTriggerEnter」と「true」が両方表示されれば正常
  • 「OnTriggerEnter」だけが表示されるなら条件判定の失敗
  • どちらも表示されないならOnTriggerEnter自体が発生していない(Is Triggerの設定ミスなど)

という風に、原因特定のヒントになるかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/04 07:42

    なるほど...細かい解説ありがとうございました!これからの参考にさせていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる