2017-09-10 15 views
2

Je développe un jeu simple 2D dans l'unité, et je l'ai rencontré un problème lors de face à la collision. J'ai deux objets, un arbre et un joueur. L'arbre ne bouge pas et est représenté par quelques sprites et un collisionneur de polygones. Le joueur se déplace à l'aide d'un script personnalisé (PAS le contrôleur de caractères), et a une cinématique Ridgidbody et collisionneur de polygones ci-joint.Objet 2D Collison Unité

Mon comportement serait destiné au joueur de « Collide » avec l'arbre et être bloqué par elle, de sorte qu'aucun des objets pourrait être en mesure de se déplacer. Cependant, cela ne semble pas être un moyen simple de le faire.

Réglage RidgidBody de l'arbre composante aux résultats « statique » ou « dynamique » en collision détectés. J'ai considéré faire du joueur un corps rigide 'dynamique', mais le unity docs suggère que les corps rigides dynamiques ne devraient pas être déplacés par leur composant de transformation, ce qui est le fonctionnement de mon système actuel. De plus, le paramétrer sur dynamic entraîne un comportement inattendu où le joueur se fige sans raison, et comme aucune physique ne sera appliquée sur l'objet player, cela semble être un mauvais cas d'utilisation pour dynamic. Je pourrais juste avoir tort à ce sujet cependant.

je pourrais peut-être utiliser un script pour verrouiller en quelque sorte la position du joueur lorsqu'un événement collisionneur est déclenché, mais cela semble très hacky. Quelqu'un peut-il donner un aperçu sur la façon de gérer cela?

+1

Ajoutez le script que vous utilisez pour déplacer le joueur –

Répondre

0

Eh bien apparemment les colissions 2D sont un peu buggy peu. Voici une approche pour éviter ces problèmes. Fondamentalement, au lieu de compter sur collisionneurs, il utilise un raycast pour vérifier s'il y a un obstacle où le joueur tente de se déplacer

using UnityEngine; 
using System.Collections; 
using UnityEngine.UI; 

public class Player : MovingObjects { 

    protected override void AttemptMove<T> (int xDir, int yDir) 
    { 
     base.AttemptMove<T> (xDir, yDir); 
     RaycastHit2D hit;  
    } 
    protected override void onCantMove<T>(T component) 
    { 
     Wall hitwall = component as Wall; 
     hitwall.DamageWall (wallDamage);   
    } 

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

     int horizontal = 0; 
     int vertical = 0; 

     horizontal = (int)Input.GetAxisRaw ("Horizontal"); 
     vertical = (int)Input.GetAxisRaw ("Vertical"); 

     if (horizontal != 0) 
      vertical = 0; 

     if (horizontal != 0 || vertical != 0) 
      AttemptMove<Wall> (horizontal, vertical); 
    } 
} 

qui hérite de:

using UnityEngine; 
using System.Collections; 

public abstract class MovingObjects : MonoBehaviour { 

    public float moveTime = 0.1f; 
    public LayerMask blockingLayer; 

    private BoxCollider2D boxCollider; 
    private Rigidbody2D rb2D; 
    private float inverseMoveTime; 

    protected virtual void Start() 
    { 
     boxCollider = GetComponent<BoxCollider2D>(); 
     rb2D = GetComponent <Rigidbody2D>(); 
     inverseMoveTime = 1f/moveTime; 

    } 


    protected IEnumerator SmoothMovement(Vector3 end) 
    { 
     float sqrRemaininDistance = (transform.position - end).sqrMagnitude; 

     while (sqrRemaininDistance > float.Epsilon) { 

      Vector3 newPosition = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime*Time.deltaTime); 

      rb2D.MovePosition(newPosition); 
      sqrRemaininDistance = (transform.position - end).sqrMagnitude; 

      yield return null; 
     } 
    } 

    protected bool Move(int xDir, int yDir, out RaycastHit2D hit) 
    { 
     Vector2 start = transform.position; 
     Vector2 end = start + new Vector2 (xDir, yDir); 

     boxCollider.enabled = false; 

     hit = Physics2D.Linecast (start, end, blockingLayer); 

     boxCollider.enabled = true; 

     if (hit.transform == null) { 

      StartCoroutine(SmoothMovement(end)); 
      return true; 
     } 

     return false; 
    } 

    protected virtual void AttemptMove<T>(int xDir, int yDir) 
          where T : Component 
    { 

     RaycastHit2D hit; 
     bool canMove = Move (xDir, yDir, out hit); 

     if (hit.transform == null) 
      return; 


     Debug.Log ("Something hit", gameObject); 

     T hitComponent = hit.transform.GetComponent<T>(); 

     if (!canMove && hitComponent != null) 
      onCantMove (hitComponent); 


    } 

    protected abstract void onCantMove<T>(T component) 
         where T: Component; 

} 

Ce script appartient à un tutoriel de le site officiel de l'Unité. Un jeu 2D appelé Rogue. Voici le lien juste au cas où vous prévoyez de faire quelque chose de similaire:

https://unity3d.com/es/learn/tutorials/projects/2d-roguelike-tutorial

+1

j'ai résolu ce problème en définissant le type de corps dynamique, et l'utilisation de modèle du solide indéformable .MovePosition en combinaison avec un Vector2 pour gérer le mouvement du joueur. Merci pour votre réponse. – Jeremy

+0

Merci à vous de l'avoir accepté –