Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Martin Mundorf

Treue Seele

  • »Martin Mundorf« ist der Autor dieses Themas

Beiträge: 262

Wohnort: Waldorf, Kr. Ahrweiler

Beruf: Althistoriker

  • Private Nachricht senden

31

24.11.2017, 11:22

Hallo,


Danke schonmal fürs testen bis hier hin!

ich mußte erstmal nqachgucken was V-sync ist. Da ich ein spezielles Post-processing-Camera-Asset verwendet habe, bin ich mir nicht sicher, ob ich das zur Laufzeit abschalten kann. Vielleicht reicht es aber auch schon zum Spielstart, die Grafikqualität auf eine geringere Stufe zu setzen? :hmm:

Alle Problemchen, die mit zielen & schießen zu tun haben, sind sehr vertrakt und ich habe da schon Stunden dran gesessen um das zu beheben. Inklusive ein neues Fadenkreuz.
Ich hoffe, das ich diese Sachen (mit angebotener Hilfe eines Users) demnächst in den Griff bekomme.

Der kriech-Modus ist zurZeit nur experimental.

Das die KI einereits patroulliert und sich selbst heilen kann (zum nächsten Medipack läuft), und selbständig angreift, auf Befehl folgt ist gut, ihr sonstiges Verhalten : komisch laufen, nicht richtig zielen und treffen können ist sehr dumm und betrüblich.
Auch hier hoffe ich es, mit etwas Hilfe von euch(?) bald weiter zu kommen.

Das medipack, das sich nicht benutzen läßt, ist noch ein kleiner Fehler, da der Itemmanager das 0-te Item in der Liste nicht rausrücken kann oder will. Aber das sollte sich schnell beheben lassen, hoffe ich.

Leute ansprechen, und sie folgen zu lassen, hatte ich erst mit einem Trigger vor dem Charakter gelöst: Aber es brachte mir trotz Layer-Zuweisung zu viele Fehlermeldungen. Nun ist es ein Raycast - aber nur einer. Vielleicht experiemntiere ich da mal mit einem "Fächer" an Raycasts vor dem Spieler, damit das Ansprechen und folgen lassen können besser geht. (Wer ne bessere Idee dazu hat:nur zu. vielleicht lern ich ja noch was :) )

zum Schluß: Auch wenn es bislang ein K(r)ampf ist: Es freut mich, wenn es trotzdem schon Spaß gemacht hat.
Ich möcchte daran arbeiten, das der Krampf weniger und der Spaß mehr wird :)
"Eine Signatur ist das Buchstaben-Zahlen-Zettelchen unten an ein einem Buch in der Bibliothek!"



was ich zur Zeit ausprobiere: 3rd person Shooter <- hierfür suche ich noch Unterstützung.


"Lehrjahre": Im Lande der Hasen
mein ewiges Spielprojekt "Straights & Rows".
meine Grafiken "ohne Verwendungszweck"

Martin Mundorf

Treue Seele

  • »Martin Mundorf« ist der Autor dieses Themas

Beiträge: 262

Wohnort: Waldorf, Kr. Ahrweiler

Beruf: Althistoriker

  • Private Nachricht senden

32

17.01.2018, 17:30

Hallo zusammen :)

Nach dem sich im Hintergrund etwas getan hat seit der letzten Zwischenmeldung:
Ich möchte, daß mein Spielprojekt mehr "open World-Entdeckung" als denn nur shooter wird.
Also zB mit Quests, die man für zufällige Begegnungen der Spielewelt erfüllen kann/muß. Allerdings ist das nicht alles:

Was sollte eurer Meinung nach auch zu einem open-World-Abenteuer gehören? Ich lasse mich da gern von euch inspirieren :)

Außerdem (auch wenn das noch etwas baller-lastig ist): mein erster funktionierender Defense-Gun-Tower. (siehe Bild)
Er rotiert; wenn man ihm zu nahe kommt zielt er auf einen; die Seitenpods heben und senken sich aufs Ziel ausgerichtet, die Geschütze feuern asynchron hintereinander (mit entsprechenden Sound/Explosionseffekten).

Ich hab den Quelltext mal komplett in englisch gehalten... bin eigentlich damit zufrieden, aber vielleicht hat da ja jemand noch Verbesserungsvorschläge.
(Die Fire-Funktion wird über einen bzw. zwei Marker in der Animation aufgerufen)

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gun_Turret_2barrels : MonoBehaviour {

    [System.Serializable ]
    public class Assembly
    {
        public GameObject rotatingPart;
        public GameObject LeftPod;
        public GameObject RightPod;
        public Transform L_SPWN;
        public Transform R_SPWN;

    }
    public Assembly assembly;
    [SerializeField ]

    [System.Serializable ]
    public class Gun
    {
        [Header("Prefabs")]
        public GameObject bullet;
        public GameObject muzzleFlash;
        public AudioClip firingSound;
        public string animator_fire_bool_name;

        [Header("Settings")]
        public float repeatSearchPerSecond = 0.25f;
        public int range = 25;
        public float rotationSpeed = 15;
        public float CoolDownLeft = 0f;
        public float reloadingTime = 2.0f;
        public float firingForce = 1.0f;


    


        //public enum {Friend, Enemy, Neutral};
        [Header("Aiming")]
        public CharacterStats target;
        public List <CharacterStats> possibleTargets = new List<CharacterStats> (); 


        public enum Team 
        { Friend, Enemy, Neutral}
        public Team team;


        [Header("Effects")]
        public float Damage = 10.0f;
        public float RangeOfDamage = 7.5f;
    }
    public Gun gun;
    [SerializeField]

    private GameController gc;
    public Animator anim;
    public bool freeFire = false;

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere (this.transform.position, gun.range );
    }

    // Use this for initialization
    void Start () 
    {
        gc = GameObject.FindObjectOfType<GameController> ();
        anim = GetComponent <Animator > ();
        InvokeRepeating("search",0f, gun.repeatSearchPerSecond );
    }
    
    // Update is called once per frame
    void Update () 
    {
        if (gun.target != null) 
        {
            gun.CoolDownLeft -= Time.deltaTime;
        } 
        else 
        {
            assembly.rotatingPart .transform.Rotate (Vector3.up * Time.deltaTime * gun.rotationSpeed);
            anim.SetBool (gun.animator_fire_bool_name, false);
        }
        
    }



    void search()
    {
        
        if (gun.team == Gun.Team.Friend) {
            foreach (GameObject gO in gc.teamSP.Feinde) {
                if (gO != null && (!gun.possibleTargets.Contains (gO.GetComponent <CharacterStats > ())))
                    gun.possibleTargets.Add (gO.GetComponent<CharacterStats> ());
                //  Debug.Log (gO.name);
            }
        } else if (gun.team == Gun.Team.Enemy) {
            foreach (GameObject gO in gc.teamSP.Freunde) {
                if (gO != null && (!gun.possibleTargets.Contains (gO.GetComponent <CharacterStats > ())))
                    gun.possibleTargets.Add (gO.GetComponent<CharacterStats> ());
                //  Debug.Log (gO.name);
            }

        }

        gun.target   = null;
        float dist = Mathf.Infinity;

        foreach (CharacterStats e in gun.possibleTargets ) 
        {

            float d = Vector3.Distance (this.transform.position, e.transform.position);

            //if (naechster == null || d < dist) 
            if (gun.target  == null && d < gun .range )
            {
                //  einstellungen .rotiert = false;
                gun.target  = e;
                dist = d;


            }
        }
        //Debug.Log (naechster);
        //Debug.Log (enemies .Count );


        if (gun.target == null) 
        {
            return;
        }

        if (gun.target == null) 
        {
            gun.possibleTargets.Clear ();
            return;
        } 


            Vector3 dir = gun.target.transform.position - this.transform.position;
            Quaternion lookRot = Quaternion.LookRotation (dir);
            assembly.rotatingPart.transform.rotation = Quaternion.Euler (0, lookRot.eulerAngles.y, 0);


            Vector3 dirL = gun.target.transform.position - assembly.LeftPod.transform.position;
            Quaternion L_lookRot = Quaternion.LookRotation (dirL);
            assembly.LeftPod.transform.localRotation = Quaternion.Euler (L_lookRot.eulerAngles.x, 90, 0);

            Vector3 dirR = gun.target.transform.position - assembly.RightPod.transform.position;
            Quaternion R_lookRot = Quaternion.LookRotation (dirR);
            assembly.RightPod.transform.localRotation = Quaternion.Euler (R_lookRot.eulerAngles.x, 90, 0);



            if (gun.CoolDownLeft <= 0 && dir.magnitude <= gun.range) 
            {
                gun.CoolDownLeft = gun.reloadingTime;

                if (gun.target.egS.health > 0) 
                {
                    if (Vector3.Distance (gun.target.transform.position, this.transform.position) < gun.range) 
                    {
                        gun.firingForce = dir.magnitude;    
                    anim.SetBool (gun.animator_fire_bool_name, true);
                    }
                }
                else 
                {
                    gun.target = null;
                anim.SetBool (gun.animator_fire_bool_name, false);
                    search ();
                }
            }
            gun.possibleTargets.Clear ();
        }


    void fire_L()
    {
        fire (assembly .L_SPWN, gun.muzzleFlash , gun.firingSound ,gun.bullet , gun.firingForce  );
    }

    void fire_R()
    {
        fire (assembly .R_SPWN, gun.muzzleFlash , gun.firingSound ,gun.bullet , gun.firingForce  );
    }


    void fire(Transform spwn, GameObject muzfl, AudioClip firesnd, GameObject bull, float gunfirfor )
    {
        gunfirfor += 10.0f;

        GameObject münf = Instantiate (muzfl, spwn.position, Quaternion.identity) as GameObject;
        GameObject bullet = Instantiate (bull, spwn.position, Quaternion.identity) as GameObject; 
        AudioSource.PlayClipAtPoint (firesnd , spwn .position, 1.0f);
        bullet.transform.rotation = Quaternion.AngleAxis (90, Vector3.forward);
        bullet.transform.parent = null;
        bullet.GetComponent <Rigidbody > ().AddForce ( spwn .forward * gunfirfor , ForceMode.Impulse);
    }

}
»Martin Mundorf« hat folgendes Bild angehängt:
  • rottran.png
"Eine Signatur ist das Buchstaben-Zahlen-Zettelchen unten an ein einem Buch in der Bibliothek!"



was ich zur Zeit ausprobiere: 3rd person Shooter <- hierfür suche ich noch Unterstützung.


"Lehrjahre": Im Lande der Hasen
mein ewiges Spielprojekt "Straights & Rows".
meine Grafiken "ohne Verwendungszweck"

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

33

17.01.2018, 17:45

Ich gebe erstmal nur ein paar Kommentare zum Code ab :)

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    void search()
    {
        
        if (gun.team == Gun.Team.Friend) {
            foreach (GameObject gO in gc.teamSP.Feinde) {
                if (gO != null && (!gun.possibleTargets.Contains (gO.GetComponent <CharacterStats > ())))
                    gun.possibleTargets.Add (gO.GetComponent<CharacterStats> ());
                //  Debug.Log (gO.name);
            }
        } else if (gun.team == Gun.Team.Enemy) {
            foreach (GameObject gO in gc.teamSP.Freunde) {
                if (gO != null && (!gun.possibleTargets.Contains (gO.GetComponent <CharacterStats > ())))
                    gun.possibleTargets.Add (gO.GetComponent<CharacterStats> ());
                //  Debug.Log (gO.name);
            }

        }

Das geht kürzer und ohne doppelten Code:

C#-Quelltext

1
2
3
foreach (GameObject gO in (gun.team == Gun.Team.Friend ? gc.teamSP.Feinde : gc.teamSP.Freunde)) {
    // ...
}


C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        gun.target   = null;
        float dist = Mathf.Infinity;

        foreach (CharacterStats e in gun.possibleTargets ) 
        {

            float d = Vector3.Distance (this.transform.position, e.transform.position);

            //if (naechster == null || d < dist) 
            if (gun.target  == null && d < gun .range )
            {
                //  einstellungen .rotiert = false;
                gun.target  = e;
                dist = d;


            }
        }

Diese Schleife ergibt so keinen Sinn. Ich nehme an, du willst eigentlich das Ziel mit der kürzesten Entfernung angreifen, oder? Was du jedoch tust: Du nimmst das erstbeste Ziel, solange es in der Reichweite der Kanone ist, und danach passiert gar nichts mehr. Dann könntest du die Schleife genauso gut direkt abbrechen (mit break).

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
        if (gun.target == null) 
        {
            return;
        }

        if (gun.target == null) 
        {
            gun.possibleTargets.Clear ();
            return;
        }

Das zweite if kann nie betreten werden, da das erste schon aus der Methode rausspringt!
Es wäre besser, gun.possibleTargets.Clear (); vor der Befüllung der Liste aufzurufen.

C#-Quelltext

1
2
3
4
5
6
7
8
9
    void fire_L()
    {
        fire (assembly .L_SPWN, gun.muzzleFlash , gun.firingSound ,gun.bullet , gun.firingForce  );
    }

    void fire_R()
    {
        fire (assembly .R_SPWN, gun.muzzleFlash , gun.firingSound ,gun.bullet , gun.firingForce  );
    }

Doppelter Code! Lieber eine einzige Methode daraus machen, die einen Parameter bekommt, der dir sagt, ob die linke oder rechte Kanone feuern soll.

Martin Mundorf

Treue Seele

  • »Martin Mundorf« ist der Autor dieses Themas

Beiträge: 262

Wohnort: Waldorf, Kr. Ahrweiler

Beruf: Althistoriker

  • Private Nachricht senden

34

17.01.2018, 19:20

hmmm... :hmm:
ich hab alle vorgeschlagenen Änderungen (bis auf die letzte, da kann ich in der Animation irgendwie nicht die beiden Spawn-Punkte(als Transform) in die fire-Functiojn übergeben) mal übernommen.
Jetzt ist es so, daß das target nie null ist, d.h. das Teil rotiert nicht mehr, da der nächste Gegner anvisiert wird, auch wenn sich dieser außerhalb der Reichweite befindet.

Aus diesem Grunde hatte ich ja bei der "closest enemy"-Passage etwas herumgefrickelt.

nun sieht das bei mir so aus:
any suggestions? :hmm:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    gun.target = null;
        float dist = Mathf.Infinity;

        foreach (CharacterStats c in gun.possibleTargets) 
        {
            float d = Vector3.Distance (this.transform.position, c.transform.position);
            if (gun.target == null || d < dist) 
            {
                gun.target = c;
                dist = d;
            }
        }


        if (gun.target == null) 
        {
            return;
        }
"Eine Signatur ist das Buchstaben-Zahlen-Zettelchen unten an ein einem Buch in der Bibliothek!"



was ich zur Zeit ausprobiere: 3rd person Shooter <- hierfür suche ich noch Unterstützung.


"Lehrjahre": Im Lande der Hasen
mein ewiges Spielprojekt "Straights & Rows".
meine Grafiken "ohne Verwendungszweck"

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

35

17.01.2018, 19:31

Das if kannst du weiter vereinfachen. if (d < dist) hat denselben Effekt, denn jede Distanz ist kleiner als unendlich.
Du prüfst jetzt aber nicht mehr, ob das Ziel überhaupt in Reichweite ist. Das kannst du tun, indem du dist anfangs nicht auf unendlich setzt, sondern auf die maximale Reichweite der Kanone. Also:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gun.target = null;
float dist = gun.range;

foreach (CharacterStats c in gun.possibleTargets) 
{
    float d = Vector3.Distance (this.transform.position, c.transform.position);
    if (d < dist) 
    {
        gun.target = c;
        dist = d;
    }
}

if (gun.target == null) 
{
    return;
}

Aber nun frage dich mal: Warum überhaupt die zwei getrennten Schritte? Warum zuerst alle möglichen Ziele in einer Liste sammeln und dann nochmal in dieser Liste das nächste Ziel suchen (und danach die Liste nicht mehr benutzen)? Das könnte man doch direkt in einem Rutsch machen, ohne irgendeine Liste zu speichern.

Martin Mundorf

Treue Seele

  • »Martin Mundorf« ist der Autor dieses Themas

Beiträge: 262

Wohnort: Waldorf, Kr. Ahrweiler

Beruf: Althistoriker

  • Private Nachricht senden

36

17.01.2018, 20:55

hmm... da fragste mich wat...

Die Idee hinter der Liste war ja, das dieser Tower wenn überhaupt nur eine Gruppe aus der großen Gruppe aller Charaktere angreifen soll, und das auch nur dann, wenn sie in Reichweite sind.
Also nicht auf Neutrale oder Verbündete. Die Liste sollte eigentlich ein Filter sein.
Und weil im Spielverlauf ja aus dieser Liste ein Charakter anderweitig sterben kann, wird die Liste aktualisiert, damit kein missing-Object -Fehler auftaucht...
(das war zumindest mein Gedankengang)

Was das mit dem "auf einen Rutsch" betrifft...da steh ich grad aufm Schlauch. Ich seh es nicht :hmm: :search:
"Eine Signatur ist das Buchstaben-Zahlen-Zettelchen unten an ein einem Buch in der Bibliothek!"



was ich zur Zeit ausprobiere: 3rd person Shooter <- hierfür suche ich noch Unterstützung.


"Lehrjahre": Im Lande der Hasen
mein ewiges Spielprojekt "Straights & Rows".
meine Grafiken "ohne Verwendungszweck"

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

37

17.01.2018, 21:00

So eine Liste zu "pflegen" ist umständlich. Meine Idee war, jedes Mal (oder meinetwegen jede Sekunde oder so) alle potenziellen Ziele durchzugehen und sich dabei das mit der geringsten Entfernung zu merken, ohne irgendeine Liste zu speichern.

Hast du meinen Tipp zur Berücksichtigung der Reichweite der Kanone umgesetzt?

Martin Mundorf

Treue Seele

  • »Martin Mundorf« ist der Autor dieses Themas

Beiträge: 262

Wohnort: Waldorf, Kr. Ahrweiler

Beruf: Althistoriker

  • Private Nachricht senden

38

17.01.2018, 21:12

j, das hab ich umgesetzt - funktioniert wie es soll :)


Ha... ich glaub, jetzt hab ich auch verstanden, was du meinst :!: :D
Ich hab in meinem "GameController"die Freunde/Feinde/Neutrale als GameObjects gespeichert, und wollte, um ein ständiges getComponent zu umgehen, nur eine Liste aus den CharacterStats-Skripten.

jetzt hab ichs so gelöst:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        float dist = gun.range;
        foreach (GameObject gO in (gun.team == Gun.Team.Friend ? gc.teamSP.Feinde :  gc.teamSP.Freunde))
        {
            if (gO != null && (!gun.possibleTargets.Contains (gO.GetComponent <CharacterStats > ())))
            {               
                float d = Vector3.Distance (this.transform.position, c.transform.position);
                if (d < dist) 
                {
                    gun.target = gO.GetComponent <CharacterStats > ();
                    dist = d;

                }
            }
        }


(hier lernt man ja noch richtig was! :D )
"Eine Signatur ist das Buchstaben-Zahlen-Zettelchen unten an ein einem Buch in der Bibliothek!"



was ich zur Zeit ausprobiere: 3rd person Shooter <- hierfür suche ich noch Unterstützung.


"Lehrjahre": Im Lande der Hasen
mein ewiges Spielprojekt "Straights & Rows".
meine Grafiken "ohne Verwendungszweck"

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

39

17.01.2018, 21:14

Ich meinte eigentlich, die Liste possibleTargets komplett wegzulassen ;)

Martin Mundorf

Treue Seele

  • »Martin Mundorf« ist der Autor dieses Themas

Beiträge: 262

Wohnort: Waldorf, Kr. Ahrweiler

Beruf: Althistoriker

  • Private Nachricht senden

40

17.01.2018, 21:18

ach Mist ... die ist auch weg... orrr(grad hat sich wieder MonoDevelop wieder verabschiedet :cursing: )

sooo...jetzt aber...: 8)

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        float dist = gun.range;
        foreach (GameObject gO in (gun.team == Gun.Team.Friend ? gc.teamSP.Feinde :  gc.teamSP.Freunde))
        {
            if (gO != null )
            {               
                float d = Vector3.Distance (this.transform.position, gO.transform.position);
                if (d < dist) 
                {
                    gun.target = gO.GetComponent <CharacterStats > ();
                    dist = d;

                }
            }
        }
"Eine Signatur ist das Buchstaben-Zahlen-Zettelchen unten an ein einem Buch in der Bibliothek!"



was ich zur Zeit ausprobiere: 3rd person Shooter <- hierfür suche ich noch Unterstützung.


"Lehrjahre": Im Lande der Hasen
mein ewiges Spielprojekt "Straights & Rows".
meine Grafiken "ohne Verwendungszweck"

Werbeanzeige