Jump to content
Unity Insider Forum
  • Announcements

    • Lars

      Allgemeine Forenregeln   03/13/2017

      Forenregeln Nimm dir bitte einen Moment um die nachfolgenden Regeln durchzulesen. Wenn du diese Regeln akzeptierst und die Registration fortsetzen willst, klick einfach auf den "Mit der Registrierung fortfahren"-Button. Um diese Registration abzubrechen, klick bitte einfach auf den "Zurück" Button deines Browsers. Wir garantieren nicht für die Richtigkeit, Vollständigkeit und Brauchbarkeit der Nachrichten und sind auch nicht dafür verantwortlich. Die Beiträge drücken die Meinung des Autors des Beitrags aus, nicht zwangsläufig das, wofür die Forensoftware steht. Jeder Nutzer, der denkt, dass ein veröffentlichter Beitrag unzulässig bzw. störend ist, ist aufgefordert uns unverzüglich per E-Mail zu kontaktieren. Wir haben das Recht störende Beiträge zu löschen und bemühen uns, das in einem realistischem Zeitraum zu erledigen (sofern wir beschlossen haben, dass die Löschung notwendig ist). Du akzeptierst, durchgehend während der Nutzung dieses Services, dass du dieses Forum nicht dazu missbrauchen wirst, Inhalte zu veröffentlichen, welche bewusst falsch und/oder verleumderisch, ungenau, beleidigend, vulgär, hasserfüllt, belästigend, obszön, sexuell belästigend, bedrohlich, die Privatsphäre einer Person verletzend oder in irgend einer Art und Weise das Gesetz verletzen. Des Weiteren akzeptierst du, dass du keine urheberrechtlich geschützte Inhalte ohne Erlaubnis des Besitzers in diesem Forum veröffentlichst. Mit dem Klick auf den "Mit der Registrierung fortfahren"-Button, akzeptierst du zudem unsere Datenschutzerklärung und stimmst der Speicherung deiner IP-Adresse und personenbezogenen Daten zu, die dafür benötigt werden, um dich im Falle einer rechtswidrigen Tat zurückverfolgen zu können bzw. permanent oder temporär aus dem Forum ausschließen zu können. Es besteht keine Pflicht zur Abgabe der Einwilligung, dies erfolgt alles auf freiwilliger Basis.   Zusatzinformationen Der Forenbetreiber hat das Recht, Nutzer ohne Angabe von Gründen permanent aus dem Forum auszuschließen. Des Weiteren hat er das Recht, Beiträge, Dateianhänge, Umfrage, Blogeinträge, Galleriebilder oder Signaturen ohne Angabe von Gründen zu entfernen. Mit der Registrierung verzichtest du auf alle Rechte an den von dir erstellten Inhalten, bzw. treten diese an das Unity-Insider.de und Unity-Community.de ab. Dies bedeutet im Klartext, dass das Unity-Insider.de und Unity-Community.de frei über deine Texte verfügen kann, sofern diese nicht wiederum die Rechte anderer verletzen. Es besteht weiterhin kein Anspruch von registrierten Nutzern bzw. ehemaligen registrierten Nutzern darauf, dass erstellte Inhalte und/oder die Mitgliedschaft (User) wieder gelöscht werden (Erhaltung der Konsistenz dieses Forums).   Einwilligungserklärung Wenn du mit der Speicherung deiner personenbezogenen Daten sowie den vorstehenden Regeln und Bestimmungen einverstanden bist, kannst du mit einem Klick auf den Mit der Registrierung fortfahren-Button unten fortfahren. Ansonsten drücke bitte Zurück. Stand: 07.03.2011
Sign in to follow this  
@kuma:0

Benötige Hilfe für GnatAttack (MarioPaint Minispiel) angelehntes Spiel - BoxCollider2D nur bei Mausklick aktivieren

Recommended Posts

Hallo zusammen,

bin erst kürzlich in Unity eingestiegen, nachdem ich bereits zuvor ein Buch zum entwickeln von Spielen in C++ durchgearbeitet habe, und einige Tutorials zu Unity. Habe lediglich Grundwissen in Programmiersprachen Java und C++. Im Zuge der Durcharbeitung von dem Buch und den Tutorials habe ich auch erste Spiele entwickelt. Nun möchte in Unity mein erstes, eigenes Spiel entwickeln.

Es soll ein Spiel werden, dass an das Minispiel innerhalb von Mario Paint (Gnat Attack), angelehnt ist.  

Was ich bisher habe:

  • Einen Hintergrund für das Spielgeschehen
  • EInen animierten Sprite des Spielers (Fliegenklatsche).
  • Die Fliegenklatsche wird mit der Maus oder auf Android Geräten mit Touch-Eingabe gesteuert.Bei Mausklick schlägt man mit der Fliegenklatsche zu (Animation)
  • Sprites von zwei unterschieldichen Gegnertypen mit Animation (Spinnen Gegnertyp, Fliegen Gegnertyp) 
  • Gegner werden in unterschiedlichen Wellen gespawnt. Eine Welle stellt ein Level dar. Je höher der Level, desto mehr Gegner werden gespawnt und die Gegner werden schneller

Was mir nun Schwierigkeiten bereitet ist die Kollisionabfrage zwischen Spieler (Fliegenklatsche) und Gegner.

Was ich hinbekommen habe ist, dass man die Gegner verschwinden lässt, durch einen Mausklick, oder Touch-Eingabe direkt auf die Gegner. Ich möchte nun aber, dass nur die Fliegenklatsche (nicht die Hand die Ihn hält) die Gegner verschwinden lassen kann; und das auch nur wenn die Rechte Maustaste geklickt wurde (also wenn die Fliegenklatsche heruntergeschwungen wird).

Meine Idee war nun, dass ich über ein MouseButtonDown Event den Trigger des Boxcolliders der Fliegenklatsche deaktiveren und aktivieren lasse. Das funktioniert auch, jedoch ist das Timing unpraktisch. 

Während ich das Spiel laufen lasse, kann ich in dem Inspector sehen, dass der Trigger des BoxColliders2D bei Mausklick für einen sehr kurzen Zeitraum deaktiviert wird, und anschließend wieder aktiviert. Jedoch ist das Zeitfenster zu kurz, um damit die Gegner verschwinden zu lassen.

Ich kann die Gegner nur verschwinden lassen, wenn ich die Maustaste gedrückt halte, und dann über die Gegnersprites drüber hinweg scrolle...

Hier ist der Code:

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

public class Kill : MonoBehaviour
{
    BoxCollider2D boxCol;

    void Start()
    {
        boxCol = GetComponent<BoxCollider2D>();
    }

    void Update () {
        if (Input.GetMouseButtonDown(0)) {
            boxCol.isEnable = false;
        }
        if (Input.GetMouseButtonUp(0))
        {
            boxCol.isEnable = true;
        }
    }

    void OnCollisionEnter2D(Collision2D otherCol)
    {

            //Debug.Log(otherCol.gameObject.name);
            if (otherCol.gameObject.CompareTag("Enemy"))
            {
                otherCol.transform.gameObject.SendMessage("KillMe", 0, SendMessageOptions.DontRequireReceiver);
            }
        }
    
}

Das hier ist der Code für die generelle Maus/Touch Steuerung (dort habe ich ursprünglich die simplere Kollisionabfrage über die direkte Maus/Touch-Eingabe ohne BoxCollider der Fliegenklatsche drin):

using UnityEngine;
using System.Collections;

public class SwatterController : MonoBehaviour
{
    public Animator anim;
    bool doInputChecking = true;
    public float speed = 1.5f;
    private Vector3 target;

    void Start()
    {
        target = transform.position;

    }

    void Update()
    {


        if (Input.touchCount > 0)
        {
            if (Input.GetTouch(0).phase == TouchPhase.Began)
                CheckInput(Input.GetTouch(0).position);
            target = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
            target.z = transform.position.z;
        }
        else
        {
            if (Input.GetMouseButtonDown(0))
                CheckInput(Input.mousePosition);
            target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            target.z = transform.position.z;
        }
        transform.position = Vector3.MoveTowards(transform.position, target, speed * 5);
    }

    void CheckInput(Vector3 pos)
    {

        if (doInputChecking)
        {
            Vector3 wp = Camera.main.ScreenToWorldPoint(pos);

            Vector2 touchPos = new Vector2(wp.x, wp.y);

            anim.SetTrigger("Click");


            Collider2D otherCol = Physics2D.OverlapPoint(touchPos);

            if (otherCol)
            {
                //Debug.Log(otherCol.gameObject.name);
                if (otherCol.gameObject.CompareTag("Enemy"))
                {
                    otherCol.transform.gameObject.SendMessage("KillM", 0, SendMessageOptions.DontRequireReceiver);
                }
            }
        }
        anim.SetTrigger("Release");
    }


    void StopInputChecking()
    {
        doInputChecking = false;
    }


}

Ich hoffe es ist einigermaßen Verständlich geworden, und das mir hier jemand weiterhelfen kann. Leider fällt mir das ganze Scripting in Unity noch recht schwer.

 

Grüße @kuma:0

Share this post


Link to post
Share on other sites

Hi!

Bei einer Fliegenklatsche würde ich vermuten, dass nur im Moment des Klickens ein einziges Mal geschaut werden sollte, ob etwas darunter ist. Collider sind allerdings eher über gewisse Zeiträume hinweg sinnvoll, wie du schon etwas gemerkt hast.

Schau dir mal die Klasse Physics2D an. Dort findest du Funktionen, die du aufrufen kannst und die dir sagen, ob sich in diesem Moment etwas in einem bestimmten Bereich befindet, z.B. Physics2D.OverlapArea.

Share this post


Link to post
Share on other sites

Hi Sascha,

danke für deine Antwort. Ich war ja schon an dem Punkt, dass ich direkt über Mausklick, oder Touch-Eingabe, auf die Gegnersprites, diese verschwinden lassen kann. Jedoch stehe ich gerade echt auf dem Schlauch wie ich in dem bestehenden Code Abschnitt, die aktuell verwendete Methode "Physics2D.OverlapPoint" mit "Physics2D.OverlapArea" austausche.

Hier nochmal der Code, für die Maus / Touchsteuerung inklusive die Methode Physics2D.OverLapPoint, die bei Mausklick, bzw Touch-Eingabe, direkt auf den Collider er Gegnersprites, diese verschwinden lässt:

 

// SwatterController.cs

using UnityEngine;
using System.Collections;

public class SwatterController : MonoBehaviour
{
    public Animator anim;
    bool doInputChecking = true;
    public float speed = 1.5f;
    private Vector3 target;

    void Start()
    {
        target = transform.position;

    }

    void Update()
    {


        if (Input.touchCount > 0)
        {
            if (Input.GetTouch(0).phase == TouchPhase.Began)
                CheckInput(Input.GetTouch(0).position);
            target = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
            target.z = transform.position.z;
        }
        else
        {
            if (Input.GetMouseButtonDown(0))
                CheckInput(Input.mousePosition);
            target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            target.z = transform.position.z;
        }
        transform.position = Vector3.MoveTowards(transform.position, target, speed * 5);
    }

    void CheckInput(Vector3 pos)
    {

        if (doInputChecking)
        {
            Vector3 wp = Camera.main.ScreenToWorldPoint(pos);

            Vector2 touchPos = new Vector2(wp.x, wp.y);

            anim.SetTrigger("Click");


            Collider2D otherCol = Physics2D.OverlapPoint(touchPos);

            if (otherCol)
            {
                //Debug.Log(otherCol.gameObject.name);
                if (otherCol.gameObject.CompareTag("Enemy"))
                {
                    otherCol.transform.gameObject.SendMessage("KillMe", 0, SendMessageOptions.DontRequireReceiver);
                }
            }
        }
        anim.SetTrigger("Release");
    }


    void StopInputChecking()
    {
        doInputChecking = false;
    }


}

 

Share this post


Link to post
Share on other sites

Ah, ich hatte mir den Code nicht so genau angesehen und mich eher darauf bezogen:

vor 23 Stunden schrieb @kuma:0:

Meine Idee war nun, dass ich über ein MouseButtonDown Event den Trigger des Boxcolliders der Fliegenklatsche deaktiveren und aktivieren lasse. Das funktioniert auch, jedoch ist das Timing unpraktisch. 

Wenn ich das jetzt richtig verstehe, ist dein Problem, dass du nicht den Punkt, an dem sich die Maus befindet, sondern den Bereich, wo sich relativ dazu die Fliegenklatsche befindet, von Zielen befreien willst.

Ich würde dafür zwei Vector2 definieren, die dieselben Werte darstellen wie beim BoxCollider2D:

public Vector2 offset;
public Vector2 size = Vector2.one;

Damit man die Box, die von den beiden dargestellt wird, sehen kann, kannst du MonoBehaviour.OnDrawGizmosSelected nehmen:

void OnDrawGizmosSeclected()
{
  Gizmos.color = Color.yellow;
  Gizmos.DrawWireCube(transform.position + offset, size);
}

offset und size kannst du dann für die Berechnung der Parameter von Physics2D.OverlapArea benutzen. So kannst du einen Bereich definieren wie bei einem BoxCollider2D, nur halt ohne tatsächlich einen Collider zu haben.

Share this post


Link to post
Share on other sites

Ja - ganz genau das möchte ich umgesetzt kriegen :)

An welcher Stelle soll ich die Methode OnDrawGizmosSelected einfügen? Ich bekomme aktuell folgenden Error Code in der Konsole, sobald ich die Methode einfüge:

Assets/Scripts/SwatterController.cs(43,39): error CS0121: The call is ambiguous between the following methods or properties: `UnityEngine.Vector3.operator +(UnityEngine.Vector3, UnityEngine.Vector3)' and `UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)'

Muss ich die Beiden Vektoren (Offset und Size) mit denselben Werten initialisieren, wie den ursprünglichen BoxCollider den ich für die Fliegenklatsche definiert hatte?

Die BoxCollider2D Komponente deaktiviere ich dann wieder - richtig?

Das ist der aktuelle Code:

using UnityEngine;
using System.Collections;

public class SwatterController : MonoBehaviour
{
    public Animator anim;
    bool doInputChecking = true;
    public float speed = 1.5f;
    private Vector3 target;
    public Vector2 offset;
    public Vector2 size = Vector2.one;

    void Start()
    {
        target = transform.position;

    }

    void Update()
    {


        if (Input.touchCount > 0)
        {
            if (Input.GetTouch(0).phase == TouchPhase.Began)
                CheckInput(Input.GetTouch(0).position);
            target = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
            target.z = transform.position.z;
        }
        else
        {
            if (Input.GetMouseButtonDown(0))
                CheckInput(Input.mousePosition);
            target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            target.z = transform.position.z;
        }
        transform.position = Vector3.MoveTowards(transform.position, target, speed * 5);
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCube(transform.position + offset, size);
    }

    void CheckInput(Vector3 pos)
    {

        if (doInputChecking)
        {
            Vector3 wp = Camera.main.ScreenToWorldPoint(pos);

            Vector2 touchPos = new Vector2(wp.x, wp.y);

            anim.SetTrigger("Click");


            Collider2D otherCol = Physics2D.OverlapArea(offset, size);

            if (otherCol)
            {
                //Debug.Log(otherCol.gameObject.name);
                if (otherCol.gameObject.CompareTag("Enemy"))
                {
                    otherCol.transform.gameObject.SendMessage("KillMe", 0, SendMessageOptions.DontRequireReceiver);
                }
            }
        }
        anim.SetTrigger("Release");
    }

    void StopInputChecking()
    {
        doInputChecking = false;
    }

}

 

Share this post


Link to post
Share on other sites

Ach ja... hatte ich fast befürchtet. Ändere die eine Zeile mal zu

Gizmos.DrawWireCube(transform.position + (Vector3)offset, size);

 

vor 2 Stunden schrieb @kuma:0:

Muss ich die Beiden Vektoren (Offset und Size) mit denselben Werten initialisieren, wie den ursprünglichen BoxCollider den ich für die Fliegenklatsche definiert hatte?

Jau, das wäre sinnvoll.

 

vor 2 Stunden schrieb @kuma:0:

Die BoxCollider2D Komponente deaktiviere ich dann wieder - richtig?

Kannst du sogar ganz löschen dann ;)

Share this post


Link to post
Share on other sites

Ich glaube ich übersehe noch irgendetwas grundlegendes...

Der Code läuft nun ohne zu meckern, macht aber noch nicht was er soll. Die Box welche wir mit der OverlapArea Methode erstellt haben, ist nun fix an einer bestimmten Stelle am Bildschirm und ändert sich nicht relativ zur Mausposition. 

Offset und Size habe ich einfach mit exakt denselben Werten initialisiert wie zuvor den Box Collider (den ich nun auch entfernt habe). Die Box scheint jetzt mitten auf dem Spielfeld positioniert zu sein. Wenn nun ein Gegner sich zufällig in die Mitte des Spielfelds bewegt, und ich die Maustaste drücke, dann verschwindet dieser. 

Das Skript ist dem GameObject Swatter, also der Fliegenklatsche zugeordnet. Ich bin davon ausgegangen, die durch die OverlapArea defnierte Box, würde sich auf der relativen Position des Gameobjects beziehen?

Share this post


Link to post
Share on other sites
vor 14 Minuten schrieb @kuma:0:

Ich bin davon ausgegangen, die durch die OverlapArea defnierte Box, würde sich auf der relativen Position des Gameobjects beziehen?

Nein, die ist in world space.

Die Lösung für das Problem verbirgt sich in der OnDrawGizmosSelected-Methode, die ich dir gegeben habe. Dir wird aufgefallen sein, dass die angezeigte Position stimmt. Das passiert durch Addieren von transform.position und offset.

Share this post


Link to post
Share on other sites

Ich kann in der Scene View die Box mit dem gelben Rahmen sehen. Die Box umrandet nun genau die Fliegenklatsche (siehe Screenshot)

Wenn ich das Spiel starte und die Mausbewege, sehe ich in der Scene View immernoch wie sich die gelbe Box mit der Mausposition mitbewegt. Allerdings verschwinden die Gegner dennoch nicht bei Mausklick. 

Wenn aber ein Gegner in der Mitte des Feldes ist, und es wird mit der Maus geklickt, verschwindet er... Wieso bleibt die Position immer noch "Fix" in der Mitte des Spielfelds?

 

Swatter.png

Share this post


Link to post
Share on other sites

Das kann ich dir ohne die aktuelle Version deines Codes nicht sagen ;)

Share this post


Link to post
Share on other sites

Hier nochmal der aktuelle Code:

 

using UnityEngine;
using System.Collections;

public class SwatterController : MonoBehaviour
{
    public Animator anim;
    bool doInputChecking = true;
    public float speed = 1.5f;
    private Vector3 target;
    public Vector2 offset;
    public Vector2 size = Vector2.one;

    void Start()
    {
        target = transform.position;

    }

    void Update()
    {


        if (Input.touchCount > 0)
        {
            if (Input.GetTouch(0).phase == TouchPhase.Began)
                CheckInput(Input.GetTouch(0).position);
            target = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
            target.z = transform.position.z;
        }
        else
        {
            if (Input.GetMouseButtonDown(0))
                CheckInput(Input.mousePosition);
            target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            target.z = transform.position.z;
        }
        transform.position = Vector3.MoveTowards(transform.position, target, speed * 5);
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCube(transform.position + (Vector3)offset, size);
    }

    void CheckInput(Vector3 pos)
    {

        if (doInputChecking)
        {
           // Vector3 wp = Camera.main.ScreenToWorldPoint(pos);

           // Vector2 touchPos = new Vector2(wp.x, wp.y);

            anim.SetTrigger("Click");


            Collider2D otherCol = Physics2D.OverlapArea(offset, size);

            if (otherCol)
            {
                //Debug.Log(otherCol.gameObject.name);
                if (otherCol.gameObject.CompareTag("Enemy"))
                {
                    otherCol.transform.gameObject.SendMessage("KillMe", 0, SendMessageOptions.DontRequireReceiver);
                }
            }
        }
        anim.SetTrigger("Release");
    }

    void StopInputChecking()
    {
        doInputChecking = false;
    }

}

 

Share this post


Link to post
Share on other sites

Hm... du hast auch einfach ignoriert, was ich dir geschrieben habe.

vor 4 Stunden schrieb Sascha:

Die Lösung für das Problem verbirgt sich in der OnDrawGizmosSelected-Methode, die ich dir gegeben habe. Dir wird aufgefallen sein, dass die angezeigte Position stimmt. Das passiert durch Addieren von transform.position und offset.

Also nochmal vergleichen - richtige Position:

Gizmos.DrawWireCube(transform.position + (Vector3)offset, size);

gegen falsche Position:

Physics2D.OverlapArea(offset, size);

 

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

×