Jump to content
Unity Insider Forum

ben0bi

Members
  • Gesamte Inhalte

    20
  • Benutzer seit

  • Letzter Besuch

ben0bi's Achievements

Member

Member (2/3)

2

Ansehen in der Community

  1. Ich habe die Drive-Klasse neu geschrieben und vereinfacht (max- und minForce braucht es nicht mehr.) Damit kann man sich nun realistisch im Weltraum bewegen. (Dazu muss man beim Rigidbody "Drag" auf 0 stellen.) --> @Marrrk: Das ist das Problem bei deiner Drive-Klasse: Die Geschwindigkeit wird in der Physik nicht begrenzt. Deshalb bekommt man unendliche Geschwindigkeit, wenn man bei dir "Drag" auf 0 stellt. Wenn man Enter (bei mir) drückt, dreht sich das Raumschiff - in die kürzere Richtung (wenn backThrustForce > 0) bzw. mit dem Hauptantrieb gegen die Flugrichtung und gibt DANN Gas (bzw. bremst ab) - kürzere Richtung: wenn das Schiff fast in Flugrichtung gedreht ist UND es einen "Back-Thruster" hat, dann dreht es sich VORWäRTS in Flugrichtung und bremst mit dem BACK-Thruster ab.... maxSpeed ist der Speed in Units/Sekunde. Das finde ich ein bisschen genauer als mit Force. Der Speed wird direkt an rigidbody.velocity begrenzt. sqrSpeed ist nur für die Performance da, man könnte es auch "nur" mit maxSpeed machen. Es gibt noch zwei Funktionen: "Halt" und "ResetHalt", welche in "Drive.cs" als virtual deklariert sind. Sie setzen einfach den bool isHalting auf true bzw. false. "Halt" (hier) dreht das Schiff und bremst ab. Im PlayerController noch diese Linien einfügen: DriveEffects habe ich woanders schon erklärt, das könnt ihr ignorieren. Update() { ... if(Input.GetKey(Key.Enter) drive.Halt(); else drive.ResetHalt(); ... } Hier ist mal der komplette Code, es ist mitten in der Nacht....weitere Erklärungen gibts auf Anfrage. DriveEffects könnt ihr ignorieren, bzw. hab ich schon irgendwo erklärt. Der bool backThrust sollte anders heissen, back=hinten - also wenn true = main-engine und nicht die vorderen...O.o using UnityEngine; using System.Collections; public class Drive_Thruster_noDrag : Drive { // Max velocity in units/second (?) public float maxSpeed = 20.0f; // force to push forward public float thrustForce = 300.0f; // force to push backwards public float backThrustForce = 150.0f; public float rotationForce=3000.0f; protected float currentForce; protected float sqrSpeed; protected float controlSpeed=0.0f; protected bool backThrust = false; // rotation to turn to when halting. protected Quaternion targetRotation; public override void RotateRight(float factor) { Static.FindRigidBody(transform).rigidbody.AddTorque(0, Time.deltaTime * rotationForce * factor, 0); if (driveEffects) driveEffects.RotateRight(); } public override void RotateLeft(float factor) { Static.FindRigidBody(transform).AddTorque(0, -Time.deltaTime * rotationForce * factor, 0); if (driveEffects) driveEffects.RotateLeft (); } public override void Accelerate(float factor) { currentForce = thrustForce*factor; if (driveEffects) driveEffects.Accelerate(); } public override void DeAccelerate(float factor) { currentForce = -(backThrustForce*factor); if (driveEffects) driveEffects.DeAccelerate(); } public override void Halt(float factor) { Rigidbody rb=Static.FindRigidBody(transform); if(!rb) return; Vector3 lookRotation = new Vector3(rb.velocity.x, 0.0f, rb.velocity.z); if (lookRotation == Vector3.zero) return; GameObject ship = Static.FindShip(gameObject); if (!ship) ship = gameObject; float sy = ship.transform.rotation.eulerAngles.y; if (!isHalting) { backThrust = false; if (backThrustForce > 0) { // check if forward angle is smaller than backward angle. // [TODO]: Works not properly! (y=0 / 180) float yf = Quaternion.LookRotation(lookRotation).eulerAngles.y; float yb = Quaternion.LookRotation(-lookRotation).eulerAngles.y; float forwardAngle = Mathf.Abs(sy - yf); float backwardAngle = Mathf.Abs(sy - yb); if (forwardAngle > backwardAngle) { lookRotation = -lookRotation; backThrust = true; } } else { // if there is no back thruster, just switch the forward rotation to backward, // so the main thruster looks into the forward direction. lookRotation = -lookRotation; backThrust = true; } // set the target rotation. targetRotation = Quaternion.LookRotation(lookRotation); }else{ // AI Script to rotate and stop the drives. float ty = targetRotation.eulerAngles.y; if (sy - ty >= 5.0f) { RotateLeft(1.0f); } else if (sy - ty <= -5.0f) { RotateRight(1.0f); }else{ if (rb.velocity.magnitude > 2.0f) { if (backThrust) Accelerate(1.0f); else DeAccelerate(1.0f); } } } //transform.rotation=Quaternion.LookRotation(lookRotation); base.Halt(factor); } void Update() { if (maxSpeed != controlSpeed) { controlSpeed = maxSpeed; sqrSpeed = maxSpeed * maxSpeed; } // stop the drives, they will be started when a button is pressed. if (driveEffects) driveEffects.StopDrives(); } void FixedUpdate() { Rigidbody rb = Static.FindRigidBody(transform); if (!rb) return; rb.AddForce(currentForce * Time.deltaTime * transform.forward); currentForce = 0.0f; // limit the rigidbodys velocity. var v = rb.velocity; if (v.sqrMagnitude > sqrSpeed) rb.velocity = v.normalized * maxSpeed; } }
  2. Danke, das mach ich. Ich hab isInstalled so "installiert", damit man den Wert auch im Inspektor ändern kann. Ist ein bisschen umständlich, ich weiss.... Wie ist es denn, wenn ich OnPreDamage wieder entfernen will? bzw. Ich habe jetzt umgedacht, und anstatt den Schild gleich zu "vorinstallieren" möchte ich Slots machen dafür - wo man auch was anderes reinmachen kann, wie zum Beispiel einen Hull-Repair-Bot oder so... Wie kann ich also diese Funktionen wieder entfernen? Und wie geht das mit OnDisable? (Der Schild existiert ja eventuell noch, kommt halt ins Inventar....) Danke für die Hilfe.
  3. Beim Schild habe ich ein bisschen anders verfahren: Eventuell kann mein (erstes) Schiff keinen Schild haben und zweitens weiss ich nicht, ob beim wiederholten auflesen die OnPreDamage-Funktion nochmal geadded wird. Ich habe also meinem Schiff schon von Anfang an einen Schild gegeben, mit einer bool Variable "isInstalled", welche an den wichtigen Stellen (auch in OnPreDamage() !!) abgefragt wird. Nun habe ich dem Schild noch ein Aussehen gegeben, indem ich dem eine Kugel ans Playerschiff angehängt habe. Von dieser schalte ich den Mesh-Renderer bzw. den Collider ein oder aus, je nachdem was gerade "benutzt" wird. Achja, und mein Schild fängt erst nach einer bestimmten Zeit nach dem letzten Treffer wieder an, sich aufzuladen. Hier ist der Code: [RequireComponent(typeof(Destructable))] public class Shield : MonoBehaviour { public bool isInstalled = false; public Transform meshAndCollider=null; public float strength = 100.0f; public float waitForReloadTime = 1.0f; public float reloadPerSecond = 10.0f; public float minEffectTime = 0.1f; // maybe we will change the strength of the shield directly. public float actualStrength; private bool wasInstalled; private float actualWaitTime; private float actualEffectTime; private MeshRenderer[] meshRenderer = null; private Collider[] meshCollider = null; // Use this for initialization void Start () { wasInstalled = isInstalled; if (meshAndCollider) { meshRenderer = meshAndCollider.GetComponents<MeshRenderer>(); meshCollider = meshAndCollider.GetComponents<Collider>(); } if (isInstalled) Install(); else Uninstall(); Destructable destructable = GetComponent<Destructable>(); destructable.onPreDamage += OnPreDamage; } private void Install() { isInstalled = true; actualStrength = strength; actualWaitTime = 0.0f; actualEffectTime = 0.0f; EnableRenderers(false); EnableColliders(true); } private void Uninstall() { isInstalled = false; EnableRenderers(false); EnableColliders(false); } // Update is called once per frame void Update () { // maybe install it again, check isInstalled // this is for when Install() / Uninstall() was not called but isInstalled has changed. if (wasInstalled != isInstalled) { wasInstalled = isInstalled; if (isInstalled) Install(); else Uninstall(); } if (isInstalled) { actualEffectTime += Time.deltaTime; actualWaitTime += Time.deltaTime; if (actualEffectTime >= minEffectTime) { EnableRenderers(false); actualEffectTime = minEffectTime + 1.0f; } if (actualWaitTime >= waitForReloadTime) { actualStrength += Time.deltaTime * reloadPerSecond; actualWaitTime = waitForReloadTime + 1.0f; } actualStrength = Mathf.Min(actualStrength, strength); if (actualStrength <= 0.0f) { EnableColliders(false); EnableRenderers(false); }else{ EnableColliders(true); } } } void OnPreDamage(Damage damage) { if (isInstalled) { // reset times actualWaitTime = 0.0f; if (actualStrength > 0.0f) { actualEffectTime = 0.0f; EnableRenderers(true); } var savedDamage = Mathf.Min(damage.Amount, actualStrength); actualStrength -= savedDamage; damage.Amount -= savedDamage; } } private void EnableRenderers(bool enable) { if (meshRenderer.Length > 0) { foreach (MeshRenderer renderer in meshRenderer) renderer.enabled = enable; } } private void EnableColliders(bool enable) { if (meshCollider.Length > 0) { foreach (Collider coll in meshCollider) coll.enabled = enable; } } } isInstalled kann man einfach an- oder ausschalten. meshAndCollider sollte mit dem Schild-Mesh/Collider-Gameobject befüllt werden. waitForReloadTime ist die Zeit in Sekunden, welche gewartet wird (nach dem letzten Treffer), bevor der Schild anfängt, sich wieder aufzufüllen. reloadPerSecond ist die Anzahl Schildpunkte, welche dann pro Sekunde aufgefüllt werden. minEffectTime ist die minimale Zeit, an welcher der Mesh des Schildes sichtbar ist. Der Mesh wird erst sichtbar, wenn man getroffen wird. Das ist das wichtigste in Kürze. Have Fun. Ich hoffe, ich hab nach all den Posts wo ich einfach hier nicht weitergelesen habe, auch mal wieder etwas sinnvolles gepostet. Sorry für das.
  4. uh oh das hab ich übersehen. Deins ist besser
  5. Ich habs jetzt noch nicht eingebaut, weil ich ein Inventar dazwischen schalten will. Was mir jedoch aufgefallen ist: Die Waffen-Scripts brauchen ja einen Rigidbody und ein Schiffs-gameObject (owner) Wenn man nun Prefabs hat und WaffenSlots, weiss ich eventuell nicht mehr, wie weit "hoch" ich in der Hierarchie muss. Deshalb: 1. Eine Klasse namens "isShip" erstellen und diese am Schiff anhängen. (Wenn das Schiff in einem Gruppen/Rudel-GameObject ist, dann kann ich nicht mehr einfach das "oberste" gameObject nehmen.) 2. Bei den Waffen folgende Funktion einbauen und noch zwei variablen: protected GameObject myParent; protected RigidBody myRigidBody; void GetShip() { myParent=gameObject; // first set rigidbody if(myParent.rigidBody) myRigidBody=myParent.rigidBody; bool done=false; while(!done) { if(!myParent.GetComponent<isShip>() && myParent.transform.parent) { myParent=myParent.transform.parent; }else{ done=true; } // reset rigidbody if(myParent.rigidBody) myRigidBody=myParent.rigidBody; } } Nun kann man by Fire() GetShip() benutzen und dann myParent und myRigidBody für das ownerObject bzw. den rigidbody. Habs noch nicht getestet, hoffe es funzt.
  6. Super Tutorials. Könntest du noch eins betreffend GUI/HUD und Radar bzw. Ziel-Richtungsanzeige machen? Und überhaupt, wie man ein Menü macht und einblendet, vielleicht so 3D-mässig leicht schräg oder mit der Geschwindigkeit des Raumschiffs verziehend... Das wäre der Hammer.
  7. "Realtime Shadows for Point- and Spot-Lights require Unity Pro" Also für die Benutzer der freien Version ist das sicher nützlich. Und ich will, dass das Licht immer ein bisschen leuchtet, egal wie weit weg man ist. Dafür kann mans auch brauchen. Hier ist noch der Code für die Licht-Intensität: Erst mal ein paar variablen: public float minIntensity=0.1f; public float maxIntensity=2.0f; public float range=100.0f; Und das da kommt in die Update-Funktion: //------------------------------------------------------------------------------------------------------------------- // LIGHT INTENSITY //------------------------------------------------------------------------------------------------------------------- float dist=Vector3.Distance (target.transform.position, transform.position); float actualIntensity=0.0f; if(dist>=range) { actualIntensity=minIntensity; }else{ float ir=maxIntensity-minIntensity; actualIntensity=((ir/range)*(range-dist))+minIntensity; } directionalLight.intensity=actualIntensity; Viel Spass!
  8. Kann ich das IN der Mitte der Sonne platzieren? Leuchtet es dann daraus heraus? Mal sehen. Ich möchte es nicht darüber platzieren, denn eventuell mach ich die Sonne richtig gross, wenn es denn die Engine erlaubt und es gut aussieht... Und eventuell soll ja der Schrägheits-Winkel immer gleich bleiben, dann nützt das was ^ ....ansonsten hab ich mich halt vertan, sorry. Ich werde den obigen Code nächstens noch ein bisschen anpassen für die Licht-Intensität.
  9. Also: currentForce arbeitet mit Vector3.forward - d.h. wirkt immer in die Blickrichtung des Schiffes. Das ist schon gut so, denn das ist ja die force für die Engines. Wenn ich jedoch das Schiff im Weltraum drehe, ohne Gas zu geben (currentForce=0 bzw. Alle Thruster Off) soll es sich in der ursprünglichen Richtung weiterbewegen, in welche es zuletzt geflogen ist. Süd: Vollgas Dann kein Gas, autobrake=off (wenn möglich) bzw. currentForce = 0 - > hier bremst das Schiff glaub ich schon ab, oder nicht? Dann drehen nach Nord, zum Feind hin und drauflos ballern - während man halt immer noch nach Süd driftet. Wie im Weltraum halt, wo ein Ding ohne Gegendruck ewigs weiterfliegt...und die Thruster sind der Gegendruck, doch mit currentForce fliegt das Ding NUR gerade aus. Wenn ich erst nach West geflogen bin und dann nach Norden Gas gebe, sollte das Ding nach NordWesten fliegen - kurz gesagt.
  10. ...das ist einer der geilsten Befehle, die ich in meiner 15jährigen Programmierer-Laufbahn gesehen habe. THUMPS UP! Ich hab euch noch einen Effekt gebastelt. Pseudo-Dynamisches Licht Dreht die y-Achse eines Directional-Lights relativ zu der Player-Position und der Sonnen-Position. Somit sieht es immer so aus, als würde das Schiff von der Sonne angeleuchtet werden. Also erst mal, bitte eine Sonne erstellen. Ein Directional-Light solltet ihr schon in der Szene haben. Es ist egal, wo dieses positioniert ist. Setzt bei der Rotation des Lichtes nur die X und Z Achse so wie es euch beliebt. Am besten so 30 und 60 Grad. (Meine Werte) Fügt nun an die Sonne folgendes Script an: using UnityEngine; using System.Collections; public class SunLightDirectionEffect : MonoBehaviour { public Light directionalLight; private Transform target; // Use this for initialization void Start () { // get the main cams target, that's the player ship. Camera mainCam = Camera.main; if (mainCam) { CameraController c=mainCam.GetComponent<CameraController>(); if(c) target = c.target; } } // Update is called once per frame void Update () { if (target && directionalLight) { Vector3 targetDir=target.transform.position-transform.position; float angle=Vector3.Angle(targetDir, Vector3.forward); // wrong angle on left side fix if(target.transform.position.x< transform.position.x) angle=360-angle; // get rotation and euler angles Quaternion rot=directionalLight.transform.rotation; Vector3 euler=rot.eulerAngles; // set y euler.y=angle; // revert rot to new euler angles. rot.eulerAngles=euler; // revert light.rotation to rot directionalLight.transform.rotation=rot; } } } Zieht jetzt noch euer DirectionalLight auf die entsprechende Variable im Script. Jetzt sollte das ganze schon funktionieren. Erklärung: In Start wird die Main-Kamera geholt. Diese hat einen CameraController, an den das SpielerSchiff angehängt ist. (Siehe vorige Tutorials) Wir setzen nun (unser) target auf das Spielerschiff. (Ich habe es erst mit der MainCam versucht, doch mit der Schiffsposition ist es akkurater. Vor allem wenn man zoomt oder so.) In Update wird nun kontinuierlich der Winkel zwischen den 2 Vektoren herausgefunden, und dann wird jedoch nur die y-Rotation bei der Lichtquelle gesetzt. Diese muss noch angepasst werden, wenn target.x < transform.x ist. Das hat ewigs gedauert, bis ich das raus hatte.... Leider muss man dazu (wirklich(?)) erst ein Quaternion getten, dann die eulerAngles, dann diese setzen, dann diese wieder in das Quaternion pushen und dann dieses Quaternion als DirectionalLight.transform.rotation setzen, ansonsten motzt die Engine.... Leider konnte ich das Video nicht schneiden. Ab 0.53 ist der Effekt an. Am Anfang ist er aus. Guck auf die CheckBox neben "Sun Light Direction Effect" PS: Das Licht ist hell-orange mit grossem Weissanteil. Have Fun!
  11. Mal gucken, danke. Ich weiss grad nicht genau, wie ich das implementieren soll. vector3 newDir=rigidbody.velocity + currentForce*Time.deltaTime*transform.forward ???? rigidbody.AddForce(newDir) ???? und wenn jetzt zb. x =+1 ist bei beiden Vektoren, wie verhindere ich, das x>1 (unerwünscht) wird aber trotzdem currentForce einbezogen? (ach, wenn ich doch grad den Developer-Lappi hier hätte...)
  12. Der Line-Renderer machte bei mir nur Magenta-Farbe. Man muss diesem noch ein Material zuweisen. Wenn man die Farben des Line-Renderers benutzen will, sollte man beim Material den Shader auf "Sprite/Additive" setzen. Das Material selbst braucht dann keine Farbe oder Textur. Kleiner Tipp: Bei der Linerenderer Farbe zweimal dieselbe nehmen, jedoch bei der zweiten Alpha auf 0 setzen. Somit sieht es aus, als würde die Laser-Energie zum Ende hin abnehmen. ---------------------------------------------------------------------------- EndEffekt-Lösch Problem: Ich will den End-Effekt nur spielen, wenn er auch wirklich was trifft. Deshalb habe ich StopEffect.cs umgeschrieben: fügt dort noch die Funktion Destroy() Remove() hinzu, welche einfach "Destroy(gameObject);" ausführt. Im Stop-Befehl des PulseEffects, die Effect-Stops durch (currentXEffect).Remove() ersetzen. (Destroy(currentXEffect) geht NICHT!) Bei Start unter Instantiate endEffect noch endEffect.Stop(), damit er nicht gleich spielt. Den Stop-Befehl für den Effekt so gestalten: if(particleSystem) { particleSystem.emitParticles=false; particleSystem.Clear(); } Dann noch einen Begin()-Befehl in StopEffect.cs einbauen und in ParticleStopEffect.cs oder wie das heisst: StopEffect.cs: public virtual void Begin() {}; ParticleStopEffect.cs: public override void Begin() { if(particleSystem) particleSystem.emitParticles=true; } Und diesen Begin-Befehl schreibt man in PulseEffect.cs, sowie einige Stop-Befehle: private void SetPositions() { if (ownerObject) { lineRenderer.SetPosition (0, ownerObject.transform.position); RaycastHit hit; if (Physics.Raycast (new Ray (transform.position, transform.forward), out hit, range, raycastLayerMask)) { SetEndPosition (hit.point); if (hit.collider.gameObject) { if(currentEndEffect) currentEndEffect.Begin (); var destructable = hit.collider.gameObject.GetComponent<Destructable> (); // maybe get parent object if (!destructable && hit.collider.gameObject.transform.parent) destructable = hit.collider.gameObject.transform.parent.gameObject.GetComponent<Destructable> (); // hit something if (destructable && !isStopping) { destructable.ApplyDamage (damagePerSecond * Time.deltaTime, gameObject); } }else{ if(currentEndEffect) currentEndEffect.Stop(); } } else { var position = transform.position + transform.forward * range; SetEndPosition (position); if(currentEndEffect) currentEndEffect.Stop(); } }else{ if(currentEndEffect) currentEndEffect.Stop(); } } (PS: particleSystem.Clear() ist das Zauberwort das ich das letzte mal...übersehen habe.) [EDIT: PS_2]: Anstatt particleSystem.Stop() und .Play() habe ich emitParticles auf true bzw. false gesetzt. Dann noch was: In AIController.cs sollte man die "TryFire"-Funktion VOR "if(!target) return;" setzen und dort nochmal nach dem target überprüfen und eventuell die Waffe stoppen. Sonst schiesst der Gegner immer weiter, wenn man zerstört wurde und er immer noch auf die alte Position zielt. AIController.cs // Update is called once per frame void Update () { if (!target) { SearchTarget(); } // tryfire here for exit shooting if no target is there. else stopping would be skipped. TryFire (); if (!target) { return; } ............... private void TryFire() { if (!weapon) { return; } if (target) { var targetDirection = (target.transform.position - transform.position).normalized; if (Vector3.Angle (targetDirection, transform.forward) <= FireThreshold) { weapon.StartFiring (); } else { weapon.StopFiring (); } } else { weapon.StopFiring (); } } Have Fun!
  13. Ich möchte, dass das Raumschiff realistisch im Weltraum herum fliegt. Dazu habe ich einen bool autoBrake, welcher das automatische Bremsen abschalten soll. Leider geht das nicht wie gewünscht: (Wie in einem späteren Kommentar beschrieben:) Die Partikel-Engines feuern die ganze Zeit, das sollen sie aber nicht. Das Raumschiff soll nur die ursprüngliche Richtung und Geschwindigkeit beibehalten bzw an die neue anpassen. Dazu bräuchte es einen Richtungs-Vektor, richtig? Weiss jemand, wie man den berechnet unter Einbeziehung der currentForce bzw. der alten Richtung und OHNE Input-"Befehle"? Also das Ziel ist, dass ich mit dem Raumschiff drehen und schiessen kann, ohne dass die Geschwindigkeit in der ursprünglichen Richtung abnimmt und ohne dass die Partikel-Engines feuern...also die ursprüngliche Richtung/Geschwindigkeit sollte soweit ohne "Accelerate", "DeAccelerate" und "RotateX" auskommen - hier sind die Partikel-Engines eingelinkt. Hat da jemand eine Lösung parat?
  14. ich musste bei der Kamera noch transform.LookAt(target) benutzen. Die Kamera dreht sich nun um das Spieler Schiff herum. Ansonsten ist es mir immer unten rausgeflogen....
×
×
  • Neu erstellen...