オブジェクトのy座標がゼロになったときに、オブジェクトを止めたいのですが、止まることなく動き続けてしまいます。
そのかわり、なぜかプレイヤーキャラのy座標がうごかなくなります。
状況としては、y軸のマイナス側からプラスに向かってオブジェクトが動き、それを0のところで止めたい、というものです。
解決方法を教えてください。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Trap2 : MonoBehaviour { public GameObject TrapSpike2; public float trap2speed; Rigidbody2D rigidTrap2; void Start() { rigidTrap2 = TrapSpike2.GetComponent<Rigidbody2D>(); } public void Trap2Activate() { rigidTrap2.velocity = new Vector2(0, trap2speed); if (rigidTrap2.position.y >= 0 ){//ここで止めようとしました。 >=の他にも==も試しました。 { rigidTrap2.velocity = new Vector2(0, 0); } } } コード
using UnityEngine; public class PlayerManager : MonoBehaviour { //public public float xspeed; public float jumpPower; public GroundCheck ground; public GameManager gameManager; //SE [SerializeField] AudioClip jumpSE; public Traps trap1; public Trap2 trap2; //private private bool isGround = false; float speed; bool isDead = false; AudioSource audioSource; public enum DIRECTION_TYPE { STOP, RIGHT, LEFT } DIRECTION_TYPE direction = DIRECTION_TYPE.STOP; Rigidbody2D rigidbody2D; Rigidbody2D trapSpike1; Animator animator; private void Start() { rigidbody2D = GetComponent<Rigidbody2D>(); trapSpike1 = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); audioSource = GetComponent<AudioSource>(); } void Update() { if (isDead) { return; } //接地判定を得る isGround = ground.IsGround(); float x = Input.GetAxis("Horizontal"); //speedというパラメータにxを代入 animator.SetFloat("speed", Mathf.Abs(x)); if (x == 0) { //止まっている direction = DIRECTION_TYPE.STOP; } else if (x > 0) { //右に動く direction = DIRECTION_TYPE.RIGHT; } else if (x < 0) { //左に動く direction = DIRECTION_TYPE.LEFT; } //スペース押したらジャンプ if (isGround) { if (Input.GetKeyDown("space")) { Jump(); } else { animator.SetBool("isJumping", false); } } switch (direction) { case DIRECTION_TYPE.STOP: speed = 0; break; case DIRECTION_TYPE.RIGHT: speed = xspeed; transform.localScale = new Vector3(1, 1, 1); break; case DIRECTION_TYPE.LEFT: speed = -xspeed; transform.localScale = new Vector3(-1, 1, 1); break; } rigidbody2D.velocity = new Vector2(speed, rigidbody2D.velocity.y); } void Jump() { //上に力を加える rigidbody2D.AddForce(Vector2.up * jumpPower); animator.SetBool("isJumping", true); audioSource.PlayOneShot(jumpSE); } private void OnTriggerEnter2D(Collider2D collision) { if (isDead) { return; } if (collision.gameObject.tag == "Trap") { Debug.Log("GameOver"); gameManager.GameOver(); PlayerDeath(); } if (collision.gameObject.tag == "Finish") { Debug.Log("GameClear"); gameManager.GameClear(); } //トラップSwitchのタグ if (collision.gameObject.tag == "Switch1") { Debug.Log("罠1起動"); trap1.Trap1Activate(); } if (collision.gameObject.tag == "Switch2") { Debug.Log("罠2起動"); trap2.Trap2Activate(); } if (collision.gameObject.tag == "Switch3") { Debug.Log("ブロック出現"); //trap2.Trap2Activate(); } } void PlayerDeath() { BoxCollider2D boxCollider2D = GetComponent<BoxCollider2D>(); Destroy (boxCollider2D); rigidbody2D.velocity = new Vector2(0,0); rigidbody2D.AddForce(Vector2.up * 400); animator.Play("PlayerDeathAnimation"); gameManager.GameOver(); isDead = true; } } コード
憶測ですみませんが、プレーヤーオブジェクトが影響を受けるとしたら、
rigidTrap2 = TrapSpike2.GetComponent<Rigidbody2D>();
の前に
TrapSpike2 = 参照するオブジェクト;
のようなコードが必要なのではないでしょうか。
ご回答ありがとうございます。
public GameObject TrapSpike2;
を宣言して、TrapSwitch2という判定のオブジェクトに付けたTrap2のスクリプトにTrapSpike2はアタッチしています。
そういうことではないですか?
一応図も追加しておきます。
Unityはよく知らないのですが、
public GameObject TrapSpike2;
だけでは、型宣言のみで、この妨害ブロックの実体のポインタを受け取っていないのではないかと思い、コメントしました。
ポインタというものについて詳しくはないのですが、調べてみたところ、メモリの保存領域のアドレスそのもののことですね。
それを受け取っていないとなると、TrapSpike2は全く動かないということにはなりませんか?
Trap2Activateが別のコードから呼ばれていると思いますが、どのように呼ばれていますか?
1度だけ呼ばれた場合でもvelocityが変更されますので上方向へ移動するとして、停止処理はこのメソッドが呼ばれ続けていないと行われません。
プレイヤーの不具合はプレイヤー側のコードに何か問題があるのでは?
呼び出し側のコードを追記しました。
呼び出している箇所は
if (collision.gameObject.tag == "Switch2")
{
Debug.Log("罠2起動");
trap2.Trap2Activate();
のところです。
呼ばれ続ける、ということはUpdateの中に放りこむということでしょうか。
単純な方法だとそうなります。
Trap2Activateではvelocityにspeed文の上方向への力を与えて終わり。
後の停止処理はTrap2スクリプトにvoid Update()を作ってそこに以降のif文を記入します。
それだけでも発動して止まる、という動きは再現できるはず。
例えば、
bool kidou = false;
private void Update()
{
if (!kidou) return;
rigidTrap2.velocity = new Vector2(0, trap2speed);
if (rigidTrap2.position.y >= 0 ){//ここで止めようとしました。 >=の他にも==も試しました。
{
rigidTrap2.velocity = new Vector2(0, 0);
}
}
public void Trap2Activate() {
kidou = true;
}
意味は同じです。
うまくできました。ありがとうございます。
これはkidou = trueであるかぎり上に上がろうとするのを、フレームごとにグググ、と止め続けるイメージでしょうか。
止め続ける、というよりvelocityとして与えた値を0にする条件式を実行するためには?
という事です。
Trap2Activateの中で判定をしても思っているタイミングでは判定されない、という事です。
その他の条件にもよりますが、例えばGravityScaleが0などvelocityにあたえられる抵抗がない(物理演算上)場合、
bool kidou = false;
private void Update()
{
if (!kidou) return;
if (rigidTrap2.position.y >= 0 ){//ここで止めようとしました。 >=の他にも==も試しました。
{
rigidTrap2.velocity = new Vector2(0, 0);
kidou = false;
}
}
public void Trap2Activate() {
kidou = true;
rigidTrap2.velocity = new Vector2(0, trap2speed);
}
これでも同じ動きになるはずです。
質問内容の上記において重要な部分でTrap2Activateというメソッドが実行される部分というのはCollisionで判定された一度のみで、そこでフレームにまたがる判定処理を書いても、常に判定してくれる様な仕組みにはなりませんって事です。
なるほど。そういうことだったのですね。
すごく丁寧に教えていただき、本当にありがとうございます。
助かりました。
回答1件
あなたの回答
tips
プレビュー