Jump to content
Unity Insider Forum

Mr 3d

Members
  • Content count

    672
  • Joined

  • Last visited

  • Days Won

    25

Mr 3d last won the day on September 21

Mr 3d had the most liked content!

Community Reputation

140 Excellent

About Mr 3d

  • Rank
    Christian
  • Birthday 12/09/1999

Profile Information

  • Gender
    Male
  • Location
    Bayern

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Hi, du kannst dir mit 'Quaternion.Euler(x, y, z)' deine eulerische Rotiation in einen Quaternion umrechnen lassen. Also: GameObject inst = Instantiate(shotGun, shotSpawnGun.position, Quaternion.Euler(0.0f,shotSpawnGun.rotation.y, shotSpawnGun.rotation.z)); Wenn du die drei Komponenten einfach nur in Klammern setzt, bekommst du ein Tripple was soweit ich weiß erst in einer neueren C# Version unterstützt wird (?) Syntaktisch richtig müsstest du schreiben 'new Quaternion(x, y, z, w)', aber da eh niemand Quaternions versteht, würde ich das lieber lassen.. ^^ Wenn du trotzdem wissen willst, was es mit Quaternions auf sich hat, kann ich dir dieses Video empfehlen:
  2. Mr 3d

    mit Objekten interagieren

    Ich würde fast sagen, dass ein Trigger pro Item unperformanter sein dürfte als ein Raycast pro Frame.. In einem meiner Projekte habe ich hunderte Raycasts pro Frame und selbst auf älterer Hardware habe ich keine Probleme, also sollte dein einzelner Ray nichts ausmachen.. Wenn du trotzdem Bedenken hast, würde ich wie malzbie schon meinte, einfach nur jedes x-te Frame einen Raycast schießen. Dann könntest du noch mit einer LayerMask arbeiten, damit du nur nach Items und Wänden checkst. Und du kannst jedes mal, wenn ein neues Objekt getroffen wird, dein 'IInteractable' cachen. Damit sparst du dir viele GetComponent calls, die wahrscheinlich schlimmer als der Raycast selbst sind.
  3. Mr 3d

    RayCastHit reagiert zu langsam

    Für ein 8x8 'Pixel' Feld sollte die Abfragerate zu erhöhen ganz gut funktionieren. Falls du in Zukunft aber auch mit größeren Feldern arbeiten willst, wirst du damit evtl. Performance Probleme bekommen.. Alternativ kannst du dir immer die Fingerposition vom vorherigen Frame merken und dann alle Würfel anmalen, die zwischen der alten und neuen Position liegen. Unter 'line rasterization' solltest du da fündig werden..
  4. Mr 3d

    Unreachable code detected

    Die Syntax von deinem Code ist richtig, nur denkt der Compiler schon einen Schritt weiter.. z.B. '50 > 100' wird immer eine falsche Aussage sein, daher wird die Zeile 'Console.WriteLine("50 ist grösser 100");' unter keinen Umständen ausgeführt werden. Da denkt sich der Compiler, dass das nicht richtig sein kann und gibt dir die Warnung 'Unreachable code detected' . Funktionieren sollte der Code trotzdem..
  5. Mr 3d

    Malprogramm mit Unity?

    Deine Ansatz ist schon mal nicht ganz falsch, nur nicht sehr sauber/ optimiert.. Zum einen erzeugst du jeden Update eine neue Textur, was unnötigen Datenmüll erzeugt. Und du rufst mehrfach in einem Update 'Apply()' auf. Das sorgt dafür, dass die geänderte Textur zur GPU geschickt wird. Es reicht, wenn du am Ende von jedem Update 'Apply()' aufrufst, sonst schickst du unnötig viele Daten an die GPU, wodurch viel Zeit verloren geht.. Deine Grundstruktur sollte in etwa so aussehen: public int texSize = 512; private Texture2D tex; pivate Color[] pixelColors; private void Start(){ //init textur tex = new Texture2D(texSize, texSize); pixelColors = new Color[texSize * texSize]; GetComponent<Renderer>().material.mainTexture = tex; } private void Update(){ //pixelColors ändern ApplyTexture(); } private void ApplyTexture(){ tex.SetPixels(pixelColors); tex.Apply(); } Um die Pixelfarben zu ändern, musst du erstmal errechnen, wo sich die Maus gerade auf der Textur befindet. 'Input.mousePosition' gibt dir ja nur die Position im 'Game' -Fenster.. Je nachdem, wie du die Textur anzeigen lässt, kannst du das per 'mainCam.ScreenToWorldPoint()' + etwas Mathe machen, oder du schießt einen Ray auf deine Zeichenfläche und lässt dir von 'RaycastHit' die getroffenen UV Position auf der Textur geben. Wenn du dann die X- & Y- Koordinate ( zwischen 0 bis 'texSize' ) errechnet hast, kannst du den Index des getroffenen Pixels im 'pixelColors' Array errechnen: int pixelIndex = xCoord + yCoord * texSize; pixelColors[pixelIndex] = Color.red; Soviel zu den Basics.. wenn du aber vorhast ein 'richtiges' Malprogramm zu basteln, würde ich einen Shader verwenden, weil die um einiges performanter sind.. Ich hatte das selbst vor ein paar Monaten mal getestet.. Ich hab sogar noch den Code gefunden, falls dich die Methode mit dem Shader interessiert. Ich könnte das auch nochmal genauer erklären, aber das ist etwas aufwendiger.. // gab es nicht mal so ein 'Spoiler' Button, mit dem man den Code ein-/ausklappen kann? TexturePaint.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class TexturePaint : MonoBehaviour { public Texture2D source; public Transform target; public Shader myShader; private Mesh targetMesh; private Vector2 targetDimensions; public Color BrushColor; private RenderTexture tmpEditTexture; private Material CircleBrush; private int width; private int height; private Camera cam; private Vector2 lastUV; private bool startStroke; void Awake () { width = source.width; height = source.height; cam = Camera.main; CircleBrush = new Material(myShader); tmpEditTexture = new RenderTexture(width, height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB); Graphics.Blit(source, tmpEditTexture); target.GetComponent<Renderer>().material.mainTexture = tmpEditTexture; targetMesh = target.GetComponent<MeshFilter>().mesh; targetDimensions = new Vector2(targetMesh.bounds.size.x, targetMesh.bounds.size.z); } private void Update() { if (Input.GetMouseButtonDown(0)) { startStroke = true; } if (Input.GetMouseButton(0)) { Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition); mousePos.y = 0; mousePos = target.InverseTransformPoint(mousePos); Vector2 uv = new Vector2(1 - (mousePos.x / targetDimensions.x + .5f), 1 - (mousePos.z / targetDimensions.y + .5f)); if (startStroke) { startStroke = false; lastUV = uv; } BrushStroke(lastUV, uv); lastUV = uv; } } private void BrushStroke(Vector2 uvCoordFrom, Vector2 uvCoordTo) { CircleBrush.SetColor("_BrushColor", BrushColor); CircleBrush.SetFloat("_BrushSize", (brushSizeSlider.value / width)); CircleBrush.SetVector("_BrushLine", new Vector4(uvCoordFrom.x, uvCoordFrom.y, uvCoordTo.x, uvCoordTo.y)); RenderTexture tmp = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB); Graphics.Blit(tmpEditTexture, tmp, CircleBrush); Graphics.Blit(tmp, tmpEditTexture); RenderTexture.ReleaseTemporary(tmp); } } LineBrush.shader Shader "TexturePaint/CircleBrush" { Properties { _MainTex ( "Texture", 2D ) = "white" {} _BrushColor ( "Brush Color", COLOR ) = ( 1, 1, 1, 1 ) _BrushLine ( "Brush UV Line", VECTOR ) = ( 0, 0, 0, 0 ) _BrushSize ( "Brush Size", FLOAT ) = 0.01 } SubShader { Tags { "RenderType" = "Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _BrushColor; float4 _BrushLine; float _BrushSize; v2f vert ( appdata v ) { v2f o; o.vertex = UnityObjectToClipPos ( v.vertex ); o.uv = TRANSFORM_TEX ( v.uv, _MainTex ); return o; } float distFromLine ( float4 l, float2 p ) { return abs ( ( p.x - l.x )*( -l.w + l.y ) + ( p.y - l.y )*( l.z - l.x ) ) / sqrt ( pow ( -l.w + l.y,2 ) + pow ( l.z - l.x,2 ) ); } float4 frag ( v2f i ) : SV_Target { float4 col = tex2D ( _MainTex, i.uv ); float distLine = distFromLine ( _BrushLine, i.uv ); float distBrush = length ( _BrushLine.xy - _BrushLine.zw ); distBrush = sqrt ( distBrush*distBrush + _BrushSize*_BrushSize ); float distA = length ( i.uv - _BrushLine.xy ); float distB = length ( i.uv - _BrushLine.zw ); if ( ( distLine <= _BrushSize && distA <= distBrush && distB <= distBrush ) || distA < _BrushSize || distB < _BrushSize ) { col = _BrushColor; } return col; } ENDCG } } }
  6. Ich fände es auch schön, wenn hier mal wieder mehr gepostet werden würde. War immer sehr interessant zu sehen woran andere hier grade so arbeiten.. Hier mal wieder ein Update zu meinem Blutfluss Shader..
  7. Tatsache.. ich würde auch sagen, dass die dunkelblaue Fläche größer ist.. Ich schätze mal das liegt daran, dass zwischen der blauen und roten Fläche genau ein Streifen an Pixeln liegt, der theoretisch zu beiden Farben 50% gehört. Aber jeder Pixel muss sich für eine Farbe entscheiden und somit ist Blau um einen Pixel breiter.. Den Effekt kannst du minimieren, indem du eine höhere Auflösung verwendest. Dann hat der eine Pixel weniger Einfluss.. private Sprite generateCircleSprite(Color[] colors, int resolution) { Color[] pixels = new Color[resolution * resolution]; Vector2 center = new Vector2(resolution / 2f, resolution / 2f); float anglePerColor = 360f / colors.Length; for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { Vector2 dir = new Vector2(x + .5f, y + .5f) - center; float angle = -Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + 90; angle = (angle < 0 ? 360 + angle : angle); int colorIndex = Mathf.Min((int)(angle / anglePerColor), colors.Length - 1); pixels[x + y * resolution] = dir.magnitude < resolution * .5f ? colors[colorIndex] : Color.clear; } } Texture2D tex = new Texture2D(resolution, resolution); tex.SetPixels(pixels); tex.Apply(); return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(.5f, .5f), resolution); } Diese Methode gibt dir ein Sprite zurück, dass immer 1 Unit hoch/breit ist. Weil die Höhe/Breite in Pixeln der Textur gleich der PixelPerUnit des Sprites entspricht.. Dann kannst du die Größe deines Rades einfach mit der Transform Scale bestimmen.
  8. Die Größe des Sprites wird nicht in 'GenerateCircleTexture' bestimmt. Der Parameter setzt nur die Auflösung der Textur.. Bei 'Sprite.Create()' steht der letzte Parameter für die Anzahl der Pixel, die in 1 Unit gepackt werden. Wenn zb. deine Textur 1024 Pixel breit ist, und dein Sprite 512 PixelPerUnit hat, ist dein Sprite 2 Units groß.. Ich weiß ja nicht wie viele Farben du hinzugefügt hast, aber bei mir sehen die alle gleich groß aus..
  9. Kannst du trotzdem nachvollziehen was die Methode macht? Im 'pixels' Array sind die Farben aller Pixel gespeichert. Dann wird jeder Pixel angeschaut und berechnet wo er im Kreis liegt und dann entsprechend eingefärbt.
  10. Ja, 'rot' war kurz für 'rotation' bzw. die Gradzahl um die sich die Scheibe gedreht hat. Also in deinem Fall 'transform.eulerAngles.z' Der 'size' Parameter steht für die Höhe&Breite in Pixeln des Kreises. Ist vtl. nicht so sinnvoll das als Parameter zu übergeben. Um die Textur als Sprite verwenden zu können, musst du erst daraus ein Sprite generieren.. (https://docs.unity3d.com/ScriptReference/Sprite.Create.html) etwa so: Texture2D tex = generateCircleTexture(512); Sprite circleSprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(.5f, .5f), 512); //letzter Parameter sind Pixel pro Unit, also ist das Sprite 1 Unit groß Dann musst du von deinem Sprite Objekt auf die Image Componente zugreifen und das neue Sprite setzen.. (nicht vergessen 'using UnityEngine.UI') using UnityEngine.UI; public Image GluecksradGraphic; //-- GluecksradGraphic.sprite = circleSprite; // edit Du benutzt ja gar nicht UI.. Dann musst du auf die SpriteRenderer Componente zugreifen und den 'sprite' Parameter ändern, nicht die Textur vom Material.. GetComponent<SpriteRenderer>().sprite = circleSprite;
  11. Das ist zwar nicht falsch, aber etwas umständlich.. public Color[] colors; private Color GetCurrentColor(float rot) { float currentRotation = rot % 360; float anglePerColor = 360f / colors.Length; int ColorIndex = (int)(currentRotation / anglePerColor); return colors[ColorIndex]; } Und um den Kreis zu malen kannst du natürlich einen Shader verwenden.. aber wie thewhiteshadow schon geschrieben hat wird es nicht ganz einfach eine dynamische Anzahl an Kreissektoren mit einem Shader zu generieren.. Ich würde einfach am Anfang die Kreistextur einmal generieren lassen.. private Texture2D generateCircleTexture(int size) { Color[] pixels = new Color[size * size]; Vector2 center = new Vector2(size / 2f, size / 2f); float anglePerColor = 360f / colors.Length; for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { Vector2 dir = new Vector2(x + .5f, y + .5f) - center; float angle = -Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + 90; angle = angle < 0 ? 360 + angle : angle; int colorIndex = Mathf.Min((int)(angle / anglePerColor), colors.Length - 1); pixels[x + y * size] = dir.magnitude < size * .5f ? colors[colorIndex] : Color.clear; } } Texture2D tex = new Texture2D(size, size); tex.SetPixels(pixels); tex.Apply(); return tex; }
  12. Mr 3d

    Denkfehler beim Ray

    Erstmal ist das '== true' unnötig.. ^^ Was macht denn 'SchienenAchsentestZ()' ? Kann es sein, dass er nur einmal in die 'if' rein geht? Dann setzt er 'rayCasting' auf 'true', aber der Raycast selbst wird noch nicht durchgeführt, weshalb 'rayAufschlag' noch (0, 0, 0) ist bzw. 'zielPosition' (0, 1, -2). Danach wird der Raycast in FixedUpdate aufgerufen und 'rayAufschlag' gesetzt, aber die Zielposition wird nicht neu berechnet. Warum ziehst du denn den Raycast in die FixedUpdate? Nur weil er über 'Physics' aufgerufen wird, müssen Raycasts nicht automatisch in die FixedUpdate. Das machen sie im Beispiel in der Dokumentation zumindest auch nicht so..
  13. Mr 3d

    Vector3.Lerp nur die x achse abfragen

    Rein nach deiner Logik suchst du wohl nach 'Mathf.Lerp(float, float, float);' object.transform.position.x = Mathf.Lerp(object.position.x,transform.position.x,2 * Time.deltaTime); Nur wird das so nicht klappen, weil du, um die Position zu ändern, den ganzen Vektor überschreiben musst. Nur eine einzelne Komponente zu ändern funktioniert leider nicht. Hier eine ganz gute Erklärung dazu: https://answers.unity.com/questions/427769/gameobjecttransformpositionx-.html Du musst also erst deinen Start/End X-Wert in Vector3s umwandeln und dann den ganzen Positionsvektor überschreiben. object.transform.position = Vector3.Lerp(new Vector3(object.position.x, 0, 0), new Vector3(transform.position.x, 0, 0), 2 * Time.deltaTime); Oder du lerpst den X-Wert und wandelst ihn danach in einen Vektor um (sogar bisschen schöner): object.transform.position = new Vector3(Mathf.lerp(object.position.x,transform.position.x,2 * Time.deltaTime), 0, 0); /edit: dreifach hält besser..
  14. Mr 3d

    Text von Listenfeld ausgeben

    Und wenn du dir beim Befüllen mal die Werte von "NSumX" und "NbSumX" ausgeben lässt, nehme ich mal an, dass die Differenz genau das ist, was am Ende ausgegeben wird, oder? Wo werden denn die Werte für die PlayerPrefabs berechnet?
  15. Mr 3d

    Text von Listenfeld ausgeben

    Dann ist der Fehler beim Befüllen der Liste.. Kannst du den Code dafür mal posten? Oder hast du die Werte per Hand gesetzt?
×