# Question
Title: mapping texture uvs to sphere for skybox
I've been trying to learn shader coding, specifically procedural skyboxes. I've been using this guide here which is a shader graph tutorial and try to write out the steps in code. However, I'm stuck at the first part about fixing the texture UV's to wrap around a sphere as the current texture is warped:

Here is my current shader:

```
Shader "Unlit/TestSky"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal:NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float3 normal :NORMAL;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = normalize(UnityObjectToClipPos(v.vertex));
                o.normal = v.normal;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
             #define PI 3.141592653589793
            fixed4 frag (v2f i) : SV_Target
            {
                float3 pos = i.vertex;
                float2 newUV;
                newUV.x = 0.5 + atan2(pos.z,pos.x)/PI*2;
                newUV.y = 0.5 - asin(pos.y)/PI;

                fixed4 col = tex2D(_MainTex, i.uv);

                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

```

I also used wikipedias formula on wrapping uvs to a sphere:

However, when I go back to the Unity Editor all I see is this:

I tried using this solution:

```
Shader "Unlit/TestSky"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal:NORMAL;
            };

            struct v2f
            {
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float3 normal :NORMAL;
                float3 direction : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = (UnityObjectToClipPos(v.vertex));
                o.direction = mul(unity_ObjectToWorld, v.vertex).xyz - _WorldSpaceCameraPos;
                return o;
            }
             #define PI 3.141592653589793
            fixed4 frag (v2f i) : SV_Target
            {
                float3 pos = normalize(i.direction);
                float2 newUV;
                newUV.x = 0.5 + atan2(pos.z,pos.x)/PI*2;
                newUV.y = 0.5 - asin(pos.y)/PI;

                float2 dx = ddx(newUV);
                float2 dy = ddy(newUV);
                float2 du = float2(dx.x, dy.x);
                du -= (abs(du) > 0.5f) * sign(du);
                dx.x = du.x;
                dy.x = du.y;

                // In case you want to rotate your view using the texture x-offset.
                newUV.x += _MainTex_ST.z;

                // Sample the texture with our calculated UV & seam fixup.
                fixed4 col = tex2Dgrad(_MainTex, newUV, dx, dy);
                return col;
            }
            ENDCG
        }
    }
}

```

But ended up getting this image:

# Answer
You have mistranslated the formulas you found into code. You need to add parenthesis around the denominator in `atan2(pos.z,pos.x)/PI*2`, so change it to `atan2(pos.z,pos.x)/(PI*2)`.
> 2 votes

---
Tags: unity, shaders, fragment-shader
---


# Question
Title: How to keep player rotated toward a sphere when within a certain radius?
In my game the player can fly to multiple spheres, I want to make it so that when the player gets within a certain distance of the sphere, (maybe using a bigger is trigger sphere collider around it?) their feet will stay pointing towards the sphere until they leave the radius, (maybe using a quaternion?) then if they get within the radius of a different sphere, their feet will point towards that too. How can I make this work? I don't know too much about c#, so any example code would help a lot too!

# Answer
```
void Update () {

...

transform.rotation = Quaternion.LookRotation(forwardAxis, upAxis.z,);
}

```

this worked! although it made the camera jittery so i'll have to figure out rotation with rigidbody physics
> 0 votes

---
Tags: unity, c#
---


# Question
Title: How to render line renderer or trail renderer above UI canvas
I want to create a line renderer and also trail renderer that would follow touches but both must be rendered above my UI canvas — how can I do this?

I have tried this with the "screen space camera" mode and just came to know that it is not possible with screen space camera.

Is it possible by using line or trail with a "screen space overlay" canvas? If yes, then how could I make line/trail follow the touch position in such a setup?

I tried this before but i was not able to make it appear on screen rather it appeared on world as if it is ignoring the overlay canvas.Then I switched to screen space camera and this problem arose.

# Answer
> 3 votes
If you want to render things in front of UI then you can't achieve this with "Screen space overly" here is the reason.

So we are having two choices to chose from:

1. World space.
2. Screen space - Camera.

---

*For more information about canvas and canvas render more please visit here.*

---

> **World space:**

To achieve such a effect with world space its too easy to do, You just have to change **sorting order** or **Sorting layer** of the object to render it front or at back of the UI.

Now when we have to render **Line Rendrer** or **Trail Rendrer** in front of the UI, Then i have to change sorting order to some thing bigger then canvas sorting order, Let suppose canves sorting order is 0 then i have to change **Line or Trail rendrer** sorting order to some thing like 1 or anything bigger then 0.

**Canvas Settings:**

**Trail Rendrer Settings:**

> Or we can achieve this using **Sorting layer**. In order to use sorting layer then you have to create multiple layers. By default there is only one layer called "Default".

To create more layer you can click on **Sorting layer - Default** and then **Add Sorting Layer...**. And then just add the layers you want...

Now unity will render **sorting layer "Default"** first then on top it **Sorting layer "UI"** will be rendered and the at last **Sorting layer - Trail** will be rendered.

> **For "Screen space - Camera" same mathod will be applied like in World Space.**

I hope this will resolve the quires you have about sorting layer and sorting order and canvas render mode etc.

# Answer
> 3 votes
I needed to use Screen Space - Overlay (line renderer will not work with this), so I wrote the following code to simulate a line between two objects (it is a gameobject prefab with a black square Image component, nothing else)

```
 private void createALine(GameObject objA, GameObject objB)
{
    /*spawn a prefab image "lineConnection" as angleBar*/
    GameObject angleBar = Instantiate(lineConnection, objB.transform.position, Quaternion.identity);
    /**/
    /*calculate angle*/
    Vector2 diference = objA.transform.position - objB.transform.position;
    float sign = (objA.transform.position.y < objB.transform.position.y) ? -1.0f : 1.0f;
    float angle = Vector2.Angle(Vector2.right, diference) * sign;
    angleBar.transform.Rotate(0, 0, angle);
    /**/
    /*calculate length of bar*/
    float height = 5;
    float width = Vector2.Distance(objB.transform.position, objA.transform.position);
    angleBar.GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
    /**/
    /*calculate midpoint position*/
    float newposX = objB.transform.position.x + (objA.transform.position.x - objB.transform.position.x) / 2;
    float newposY = objB.transform.position.y + (objA.transform.position.y - objB.transform.position.y) / 2;
    angleBar.transform.position = new Vector3(newposX, newposY, 0);
    /***/
    /*set parent to objB*/
    angleBar.transform.SetParent(objB.transform, true);
}

```

---
Tags: unity, c#, gui, trail-renderer, line-renderer
---


title: Bake a heightmap from Editor

text:
# Question
Title: Bake a heightmap from Editor
I want to implement a heightmap-based water simulation algorithm in Unity. I know exactly how I would approach this in pure low-level C++ and OpenGL (and also Shadertoy), and most of it is straightforward to port to Unity.

The algorithm needs terrain height information with a heightmap. I'd like it to be flexible, so I don't want to force the user to use a terrain heightmap that has to exactly fit the area where the water is supposed to go. Instead, I'd like the user to model terrain and other static geometry in any way they want and then be able to hit a button to directly bake that geometry to a heightmap by rendering the current editor scene to a texture that is then saved as a game asset. The ortographic volume for this would be specified on the prefab that I'd create for the water simulation.

So, in short, my question is: How can I trigger a render to texture of the current scene at editor time (and save this as an asset)? And, if possible, can I specify to render only objects with a given Tag (to avoid dynamic objects in the bake)?

# Answer
> 1 votes
This was actually more straightforward than I thought. Everything that is supposed to work at runtime seems to work fine from the Editor, too. I created a script on the camera called HeightmapCamera (that does not do anything) and then added this Editor-Script:

```
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;

[CustomEditor(typeof(HeightmapCamera))]
public class EditorHeightmapCamera : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        if (GUILayout.Button("Build Object"))
        {
            var _cam = (HeightmapCamera)target;
            var rt = new RenderTexture(256, 256, 16, RenderTextureFormat.ARGB32);
            rt.Create();
            Camera cam = _cam.GetComponent<Camera>();
            cam.targetTexture = rt;
            cam.Render();
            cam.targetTexture = null;

            RenderTexture.active = rt;
            Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
            tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
            RenderTexture.active = null;

            byte[] bytes;
            bytes = tex.EncodeToPNG();

            string path = SceneManager.GetActiveScene().path.Split('.')[0] + _cam.GetHashCode() + ".png";
            System.IO.File.WriteAllBytes(path, bytes);
            AssetDatabase.ImportAsset(path);

            Debug.Log("Saved to " + path);
        }
    }
}

```

This example is just a prototype, but it succesfully creates a PNG in the folder where the scene is located. From here, it's just writing a shader that renders linear depth (depth buffer is already linear for orthographic cameras), as well as probably a 16-bit texture at least and improvements to the Editor UI that let the user choose the resolution and so on, but I'll consider my question answered with this.

---
Tags: unity, rendering, terrain, heightmap, rendertexture
---


# Question
Title: When or why would someone use a programming language (Swift, Java, C++, Rust etc...) over an engine like Unity?
Everytime I've read about people asking whether they should write their game in C++ or Unity, Unity is usually the default answer, unless they want to go through the hassle of creating an engine by themselves when Unity already does everything for you. If that's the case is there ever a case where writing a game in C++, Java, Rust etc... is better than using Unity? If so what are these cases?

# Answer
You need to write a game without an engine when you have a game with very unique technical challenges which are not sufficiently covered by general-purpose game engines.

General purpose game engines like Unreal, Unity or Godot are optimized for running any kind of game people can come up with. But a one-size-fits-all solution often has problems with handling unusual edge cases. When your game idea is such an unusual edge case (most are not), then you might have to create your own engine in order to perform the low-level optimizations you need in order to run your game with satisfying performance.

A couple games which would not have been possible (or at least very difficult) with a general purpose game engine are:

* **Minecraft**, with its millions of blocks in a single scene. Which runs so well on low-budget hardware due to the simplistic graphics and well-chosen data-structures.
* **Factorio**, which does a lot of micro- and macro-optimization to make sure it can process a huge amount of entities (their development blog is a treasure trove of interesting programming tricks).
* **Flappy Bird**. Yes, I am serious. What, you say you could do that in your favorite game engine in a couple hours? Sure, but **could you squeeze it into an APK of under a MB**? Game engines tend to add runtimes which are several MB in size to every game. Which hardly matters for a large project but seems pretty excessive for a tiny one. Filesize is also an important factor for web-based games, where every additional second of loading time will cause you to lose a couple players.

However, game engines do keep developing and become able to cover more specialized use-cases they couldn't before. Like Unity's DOTS initiative which allows to create games which require highly optimized game systems and its scriptable render pipelines which can be used to optimize for unusual render performance requirements.
> 14 votes

# Answer
The main reasons I can come up with are:

* the challenge / bragging rights / language practice. Some people just get bored when things get too easy, or they want to see what is possible without an engine.
* not knowing any better - most people are guilty of doing that at least once.
* not being dependant on an engine. That's a very ambitious thing and most of the time it's attempted by companies that want to make their own engines... either to save the money in the long run, or to make something very specialized for games they are making
* making a game for very specific environment, like certain machines that might not be able to run common engines. I think that doesn't happen very often lately though.
> 5 votes

---
Tags: software-engineering
---


title: Particle System is not Playing

text:
# Question
Title: Particle System is not Playing
I made a simple spaceship that has a particlesystem. When I press "space" button, spaceship should fly and particle system should instantiate and play. But it's not playing. It seems in hierarchy as clone but not playing.

As you see, particle effect is instantiating but not playing. It should play at bottom of spaceship

Those are codes

```
void FlyShip()
{

    if (Input.GetKey(KeyCode.Space))
    {

        rb.AddForce(Vector3.up * jumpForce);

        if (!takeoffSound.isPlaying)
        {

            // _rocketJetParticle is gameobject.
            _rocketJetParticle = Instantiate(rocketJetParticle, new Vector3(transform.position.x, transform.position.y - 4, transform.position.z), transform.rotation);
            takeoffSound.Play();

        }

    }

    else
    {
        //Destroy(_rocketJetParticle);
        takeoffSound.Stop();

    }

}

```

# Answer
> 1 votes
I found the solution.

If you instantiate a particle effect and want it to play when it instantiate you should tick "Play on Awake" box

---
Tags: unity
---


# Question
Title: How can I use one keycode key as toggle switch for two cameras?
```
using System;
using UnityEngine;
using UnityEngine.UI;
using Cinemachine;

public class CameraSwitch : MonoBehaviour
{
    public CinemachineVirtualCamera vcam;
    public CinemachineFreeLook fcam;

    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.V))
        {
            fcam.enabled = false;
            vcam.enabled = true;
        }
    }
}

```

When pressing on the V key it's switching between the cameras. I want that if I will press on the V key again it will switch between the two camera back fcam to be true and vcam to be false and so on each time pressing on the V key to switch between the cameras.

# Answer
> 2 votes
I'm assuming you tried something simple like this?

```
private void Update()
{
    if(Input.GetKeyDown(KeyCode.V))
    {
        fcam.enabled = !fcam.enabled;
        vcam.enabled = !vcam.enabled;
    }
}

```

---
Tags: unity, c#
---


# Question
Title: When an object is launched off-screen, is there any way to know if it's coming back?
In this scene, the object becomes invisible and then comes back

In this scene, the object becomes invisible but does ***not*** come back

Is there any way I can tell if an object will come back when it becomes invisible?

Edit: Thank you to S. Tarık Çetin for the solution

```
     private void Update()
     {
         if (isInvisible)
             if (IsNotComingBack())
                 OnInvisible?.Invoke();
     }

     private void OnBecameInvisible()
     {
         isInvisible = true;
     }

     private bool IsNotComingBack()
     {
         var screenLeft = _cam.ScreenToWorldPoint(_cam.transform.position).x;
         var screenRight = _cam.ScreenToWorldPoint(Vector3.right * Screen.width).x;
         var objectWidth = _spriteRenderer.bounds.extents.x;
         var isNotComingBack = transform.position.x - objectWidth < screenLeft ||
                          transform.position.x + objectWidth > screenRight;
         return isNotComingBack;
     }

```

# Answer
> 1 votes
You know `(x, y)` of the object, you also know the `(width, height)`. You know `xMin`, which is left of your screen, and `xMax`, which is right of your screen. If at any time either of these two conditions happens, it is not coming back:

1. `(x + width/2) < xMin`
2. `(x - width/2) > xMax`

Otherwise it is still within `xMin` and `xMax`, it will come down in the visible area.

You might need some other solution if the objects are not uniform scale, but this should give you the basic idea.

# Answer
> 2 votes
The equation of motion for an object accelerating under constant gravity is:

$$\vec p(t) = \vec p\_0 + \vec v\_0 t + \frac 1 2 \vec a t^2$$

...where \\$t\\$ is the number of seconds since you started tracking the object in this particular ballistic arc (eg. since the time it was launched, or time in the future from this frame), and \\$\vec p\_0\\$ and \\$\vec v\_0\\$ are the **p**osition and **v**elocity of the object at that start time \\$t = 0\\$

If you're using a physics engine with a symplectic Euler integrator like Box2D, it will have a slight integration error compared to the real physics equation above, but we can correct for that by nudging our \\$\vec v\_0\\$ term forward in time:

$$ \vec v\_{0\text{ for solving}} = \vec v\_{0 \text{ reported}} + \frac 1 2 \vec a \Delta t$$

We take whatever velocity the object has according to Box2D, and add one half a time step's worth of acceleration to it, to get the term we'll use in the equation at the top. Here \\$\Delta t\\$ is the number of seconds per simulation step.

Now we can use the quadratic formula to solve this equation to find the times \\$t^\*\\$ when the object crosses a particular height \\$y^\*\\$ \- say, the height at the top of your screen (or slightly below, if you want to make sure you see more that just the most fleeting glimpse of the object as it crosses the screen corner).

Or \\$y^\*\\$ could be the height of your ground, if you want to predict where the object will land (and neglect objects that will briefly cross the corner of the screen again before landing out of view).

$$p\_y(t^\*) = y^\*\\ p\_0{\_y} + v\_0{\_y}t^\* + \frac 1 2 a\_y {t^\*}^2 = y^\*\\ t^\* = \frac {-v\_0{\_y} \pm \sqrt{v\_0{\_y}^2 - 4(\frac 1 2 a\_y)(p\_0{\_y} - y^\*)}}{a\_y} $$

If you have no real solutions, then the object never goes off the top of the screen.

If you do have two real solutions for \\$t\\$, take the greatest one. This is the time in the future when the object falls back into the screen vertically.

Now substitute that \\$t^\*\\$ into the equation at the top, and you'll get the full position of the object at that time. Now you can measure its x coordinate to see if it's still within the screen, or too far left/right to be visible.

Be sure to take the object's dimensions, or offset from its local origin point into account when picking your \\$y^\*\\$ and left/right thresholds - they can be tighter for small objects and looser for large objects.

# Answer
> 0 votes
One generic way to handle this is to run the entire physics simulation in advance or rendering any of it and store the results for each frame in an array. You can then go through those results frame by frame to render them. If you do that you then know all of the positions for every object in the future, and can therefore work out which ones won't be coming back on screen.

This works even if things can collide with objects that are off screen and bounce back onto the screen, which I think would be possible from a bounce off the floor if the object was spinning in the right way.

Unfortunately it appears that Unity doesn't make it simple to do that. You'll probably need two copies of the scene, one of them without graphics. See https://answers.unity.com/questions/1114401/simulate-physics-without-rendering.html

# Answer
> -2 votes
If there is no need to go back to same position then an easy way is adding colliders around the scene to make a bounce back when it goes off camera

---
Tags: unity, physics, box2d, projectile-physics
---


# Question
Title: Button with hexagon shape not recognizing mouse click
I made a hexagonal button, with a png image, the problem is that if i click outside of the image of the hexagon(but still inside of the squared area that defines the whole button), the click is registered , if i click inside of the button nothing happens, now i just read in the docs about the property Click Mask, so i made the same image of the hexagon shape into a bitmap, but this error text comes up:

```
The selected resource (StreamTexture) does not match any type expected for this property (BitMap).

```

I used this linkt as a guide to create the bitmap, http://www.herongyang.com/Windows/GIMP-JPEG-Save-Image-in-BMP-Format.html, still i don't know what i'm missing. Also used MS Paint to save it as bitmap, but that din't work either.

**Why i can't load the image as Click Mask in Godot?**

I attached the image for testing.

# Answer
It seems you don't have it imported as BitMap. You will have to change the way it is imported. Make sure to save your project without continuing.

To make Godot import the image as Bitmap select the image in the FileSystem panel (on the bottom left by default), then go to the Import panel (on the top left by default, it shares dock with the Scene panel), there in "Import As:" select "BitMap", then set "Create From:" to "Black & White", and click "Reimport".

*Godot should be able to import PNG as BitMap. It does not have to be a BMP.*

Once you have it imported as BitMap, assign the image to the "Texture Click Mask" property of the `TextureButton` on the Inspector panel (on the top right by default). You can drag the image from the FileSystem panel.
> 1 votes

---
Tags: input, godot
---


# Question
Title: How to layer two textures in a cylinder without Z-fighting?
In the documentation of ShaderLab culling and depth testing you have the following:

> Offset

> Offset Factor, Units

> Allows you specify a depth offset with two parameters. factor and units. Factor scales the maximum Z slope, with respect to X or Y of the polygon, and units scale the minimum resolvable depth buffer value. This allows you to force one polygon to be drawn on top of another although they are actually in the same position. For example Offset 0, -1 pulls the polygon closer to the camera ignoring the polygon’s slope, whereas Offset -1, -1 will pull the polygon even closer when looking at a grazing angle.

I have the following scenery, it's two cylinders of the **same size**, one being the sky, one being the horizon on the floor, it is shown exactly how it is expected to render:

This is how it actually looks without playing with the offset factor and units, lots of Z-fighting:

I had to put a fairly high value to `Factor` so Z-fighting stops, around 15.

And setting the value of `Units` has absolutely no effect.

So I'm a bit at a loss as on how to correctly use both of these parameters.

**Question:**

Can you explain how shall one understand the meaning and correctly use `Factor` and `Units`?

# Answer
As @DMGregory suggested, a shader with two textures turned out to be the best choice.

```
// NOTE texture 'alpha is transparency' should be false to disable dilation

Shader "Custom/Two Textures Alpha Blending"
{
    Properties
    {
        _MainTex ("Texture 1", 2D) = "white" {}
        _NextTex ("Texture 2", 2D) = "white" {}
    }
    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 uv1 : TEXCOORD0;
                float2 uv2 : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            sampler2D _NextTex;
            float4 _MainTex_ST;
            float4 _NextTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv1 = TRANSFORM_TEX(v.uv, _MainTex);
                o.uv2 = TRANSFORM_TEX(v.uv, _NextTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // https://forum.unity.com/threads/what-is-the-formula-for-blending-two-transparent-textures-in-a-shader.169313/
                fixed4 c1 = tex2D(_MainTex, i.uv1);
                fixed4 c2 = tex2D(_NextTex, i.uv2);
                fixed3 c3 = c2.rgb * (1.0 - c1.a) + c1.rgb;
                return float4(c3, 1.0);
            }
            ENDCG
        }
    }
}

```
> 2 votes

# Answer
You should use one cylinder, in the pixel shader blend between the two textures. You may also need to generate mip maps for the textures.
> 0 votes

---
Tags: unity
---


# Question
Title: Can't correctly map uv coorditates from a fbx file on a mesh
```
#include <zlib.h>

#include "fbx_loader.h"
#include "../libs/str.h"
#include "../sys/sys_local.h"
#include "../framework/file.h"

enum Property_Value_Type {
    PROPERTY_VALUE_TYPE_BOOL,
    PROPERTY_VALUE_TYPE_S8,
    PROPERTY_VALUE_TYPE_S16,
    PROPERTY_VALUE_TYPE_S32,
    PROPERTY_VALUE_TYPE_S64,
    PROPERTY_VALUE_TYPE_REAL32,
    PROPERTY_VALUE_TYPE_REAL64,
    PROPERTY_VALUE_TYPE_STRING
};

enum Fbx_Property_Type {
    PROPERTY_TYPE_VALUE,
    PROPERTY_TYPE_VALUE_ARRAY
};

struct Fbx_Property {

    Fbx_Property_Type type;
    Property_Value_Type value_type;
    union {
        union {
            bool boolean;
            s8  int8;
            s16 int16;
            s32 int32;
            s64 int64;
            float  real32;
            double real64;
            char *string = NULL;
        } value;
        struct {
            union {
                bool *boolean;
                s32 *int32;
                s64 *int64;
                float  *real32;
                double *real64;
            };
            u32 count;
        } array;
    };
    Fbx_Property() {};
    ~Fbx_Property();
    void copy_data_to_array(u8 *data, u32 array_byte_len, u32 array_count, u8 type);
    bool is_property_type_value() { return type == PROPERTY_TYPE_VALUE; }
    bool is_property_type_value_array() { return type == PROPERTY_TYPE_VALUE_ARRAY; }
    bool is_property_value_type_string() { return value_type == PROPERTY_VALUE_TYPE_STRING; }
};

struct Fbx_Node {
    char *name = NULL;
    Array<Fbx_Property *> properties;
    Array<Fbx_Node *> sub_nodes;

    ~Fbx_Node();
    void add_property_value(FILE *file);
    bool is_null();
    u32 read(FILE *file, u32 start_offset);
};

struct Fbx_Binary_File {
    char *file_name;
    Array<Fbx_Node *> root_nodes;

    void read(const char *file_path);
    void fill_out_mesh(Triangle_Mesh *mesh);
    bool check_title(FILE *file);
    char *get_texture_name();
    Fbx_Node *find_node(const char *name);
};

Fbx_Node *find_fbx_node(const Array<Fbx_Node *> *nodes, const char *name);

static u32 property_value_type_size(u8 type)
{
    if (type == 'C' || type == 'B') {
        return 1;
    } else if (type == 'Y') {
        return 2;
    } else if (type == 'I') {
        return 4;
    } else if (type == 'F') {
        return 4;
    } else if (type == 'D') {
        return 8;
    } else if (type == 'L') {
        return 8;
    } else {
        return 0;
    }
}

static void read_primitive_type_value(Fbx_Node *node, FILE *file, u8 type)
{
    Fbx_Property *value = new Fbx_Property();
    value->type = PROPERTY_TYPE_VALUE;
    if (type == 'C' || type == 'B') {
        value->value_type = PROPERTY_VALUE_TYPE_BOOL;
        value->value.boolean = (bool)read_u8(file);
    } else if (type == 'Y') {
        value->value_type = PROPERTY_VALUE_TYPE_S16;
        value->value.int16 = read_s16(file);
    } else if (type == 'I') {
        value->value_type = PROPERTY_VALUE_TYPE_S32;
        value->value.int32 = read_s32(file);
    } else if (type == 'L') {
        value->value_type = PROPERTY_VALUE_TYPE_S64;
        value->value.int64 = read_s64(file);
    } else if (type == 'F') {
        value->value_type = PROPERTY_VALUE_TYPE_REAL32;
        value->value.real32 = read_real32(file);
    } else if (type == 'D') {
        value->value_type = PROPERTY_VALUE_TYPE_REAL64;
        value->value.real64 = read_real64(file);
    } else if (type == 'S' || type == 'R') {
        u32 len = read_u32(file);
        value->value_type = PROPERTY_VALUE_TYPE_STRING;
        value->value.string = read_string(file, len);
    } else {
        print("read_primitive_type_value can not determine type of value");
        assert(false);
    }
    node->properties.push(value);
}

static void read_array_data(Fbx_Node *node, FILE *file, u8 type)
{
    Fbx_Property *array = new Fbx_Property();
    array->type = PROPERTY_TYPE_VALUE_ARRAY;

    u32 array_count = read_u32(file);
    u32 encoding = read_u32(file);
    u64 compressed_len = read_u32(file);

    u64 array_byte_len = property_value_type_size(type - ('a' - 'A')) * array_count;
    if (encoding) {
        u8 *decompressed_buffer = new u8[array_byte_len];
        u8 *compressed_buffer = new u8[compressed_len];

        fread(compressed_buffer, sizeof(u8), compressed_len, file);
        int success = uncompress(decompressed_buffer, &array_byte_len, compressed_buffer, compressed_len);
        if (success != Z_OK) {
            print("Fbx property array decompressing failed");
        }
        array->copy_data_to_array(decompressed_buffer, array_byte_len, array_count, type);

        DELETE_PTR(decompressed_buffer);
        DELETE_PTR(compressed_buffer);
    } else {
        u8 *buffer = new u8[array_byte_len];
        fread(buffer, sizeof(u8), array_byte_len, file);
        array->copy_data_to_array(buffer, array_byte_len, array_count, type);

        DELETE_PTR(buffer);
    }
    node->properties.push(array);
}

static void read_property_value(Fbx_Node *node, FILE *file)
{
    u8 type = read_u8(file);
    if (type > 'A' && type < 'Z') {
        read_primitive_type_value(node, file, type);
    } else if (type > 'a' && type < 'z') {
        read_array_data(node, file, type);
    }
}

Fbx_Property::~Fbx_Property()
{
    if (type = PROPERTY_TYPE_VALUE_ARRAY) {
        switch (value_type) {
            case PROPERTY_VALUE_TYPE_BOOL: {
                delete array.boolean;
                break;
            }
            case PROPERTY_VALUE_TYPE_S32: {
                delete array.int32;
                break;
            }
            case PROPERTY_VALUE_TYPE_S64: {
                delete array.int64;
                break;
            }
            case PROPERTY_VALUE_TYPE_REAL32: {
                delete array.real32;
                break;
            }
            case PROPERTY_VALUE_TYPE_REAL64: {
                delete array.real64;
                break;
            }
        }
    } else {
        if (value_type == PROPERTY_VALUE_TYPE_STRING) {
            delete value.string;
        }
    }
}

void Fbx_Property::copy_data_to_array(u8 *data, u32 array_byte_len, u32 array_count, u8 type)
{
    array.count = array_count;
    if (type == 'f') {
        value_type = PROPERTY_VALUE_TYPE_REAL32;
        array.real32 = new float[array_count];
        memcpy(array.real32, data, array_byte_len);
    } else if (type == 'd') {
        value_type = PROPERTY_VALUE_TYPE_REAL64;
        array.real64 = new double[array_count];
        memcpy(array.real64, data, array_byte_len);
    } else if (type == 'i') {
        value_type = PROPERTY_VALUE_TYPE_S32;
        array.int32 = new s32[array_count];
        memcpy(array.int32, data, array_byte_len);
    } else if (type == 'l') {
        value_type = PROPERTY_VALUE_TYPE_S64;
        array.int64 = new s64[array_count];
        memcpy(array.int64, data, array_byte_len);
    } else if (type == 'b') {
        // @Node: this code isn't tested
        value_type = PROPERTY_VALUE_TYPE_BOOL;
        array.boolean = new bool[array_count];
        for (u32 i = 0; i < array_count; i++) {
            array.boolean[i] = (bool)data[i] != 0;
        }
    } else {
        assert(false);
    }
}

Fbx_Node::~Fbx_Node()
{
    if (name) {
        delete name;
    }
}

void Fbx_Node::add_property_value(FILE *file)
{
    read_property_value(this, file);
}

bool Fbx_Node::is_null()
{
    return sub_nodes.count == 0 && properties.count == 0 && strlen(name) == 0;
}

Fbx_Node *find_fbx_node(const Array<Fbx_Node *> *nodes, const char *name)
{
    for (int i = 0; i < nodes->count; i++) {
        Fbx_Node *node = nodes->at(i);
        if (node->is_null()) {
            return NULL;
        }

        if (!strcmp(node->name, name)) {
            return node;
        } else {
            Fbx_Node * searched_node = find_fbx_node(&node->sub_nodes, name);
            if (!searched_node) {
                continue;
            }
            return searched_node;
        }
    }
    return NULL;
}

u32 Fbx_Node::read(FILE *file, u32 start_offset)
{
    u32 bytes = 13;
    u32 end_offset = read_u32(file);
    u32 number_properties = read_u32(file);
    u32 property_list_len = read_u32(file);
    u8 name_len = read_u8(file);
    name = read_string(file, name_len);

    for (u32 i = 0; i < number_properties; i++) {
        add_property_value(file);
    }

    bytes += name_len;
    bytes += property_list_len;

    while (start_offset + bytes < end_offset) {
        Fbx_Node *node = new Fbx_Node();
        bytes += node->read(file, start_offset + bytes);
        sub_nodes.push(node);
    }
    return bytes;
}

void Fbx_Binary_File::read(const char *file_path)
{
    FILE *file;
    file_name = extract_file_name(file_path);

    if (fopen_s(&file, file_path, "rb")) {
        print("Fbx_Binary_FIle::read: can't open the file {}", file_name);
        return;
    }

    bool success = check_title(file);
    u32 start_offset = 27;
    while (1) {
        Fbx_Node *node = new Fbx_Node();
        start_offset += node->read(file, start_offset);
        if (node->is_null()) {
            break;
        }
        root_nodes.push(node);
    }

}

bool Fbx_Binary_File::check_title(FILE *file)
{
    bool result = true;
    u32 max_fbx_version = 7400;
    char *magic_string = new char[21];
    static char fbx_title[21] = "Kaydara FBX Binary  ";

    fread(magic_string, sizeof(u8), 21, file);
    if (strcmp(fbx_title, magic_string)) {
        print("bx_Binary_File::check_title: Fbx magic string failed, it can be not fbx file\n");
        result = false;
    }

    if (read_u8(file) != 0x1A) {
        result = false;
    }

    if (read_u8(file) != 0x00) {
        result = false;
    }

    u32 version = read_u32(file);
    if (version > max_fbx_version) {
        print("Fbx_Binary_File::check_title: File {} has unsupported version {}, needed file version {} or less", file_name, version, max_fbx_version);
        result = false;
    }
    DELETE_PTR(magic_string);
    return result;
}

Fbx_Node *Fbx_Binary_File::find_node(const char *name)
{

    Fbx_Node *node = find_fbx_node(&root_nodes, name);
    if (!node) {
        print("Fbx_Binary_File::find_node: Fbx node {} is not found in file {}", name, file_name);
    }
    return node;
}

inline void copy_fbx_mesh_data_to_triangle_mesh(Triangle_Mesh *mesh, Fbx_Property *vertex_property, Fbx_Property *uv_property, Fbx_Property *uv_index_property)
{
    for (u32 i = 0; i < mesh->vertex_count; i++) {
        //s32 uv_index = uv_index_property->array.int32[i];
        //s32 uv_index2 = uv_index_property->array.int32[i * 3 + 1];
        //s32 uv_index3 = uv_index_property->array.int32[i * 3 + 2];

        mesh->vertices[i].position.x = static_cast<float32>(vertex_property->array.real64[i * 3]);
        mesh->vertices[i].position.y = static_cast<float32>(vertex_property->array.real64[i * 3 + 1]);
        mesh->vertices[i].position.z = static_cast<float32>(vertex_property->array.real64[i * 3 + 2]);

        //mesh->vertices[i].uv.x = uv_property->array.real64[uv_index];
        //mesh->vertices[i].uv.x = uv_property->array.real64[uv_index + 1];

        //mesh->vertices[i].uv.x = 1 - uv_property->array.real64[uv_index * 2];
        //mesh->vertices[i].uv.y =  1- uv_property->array.real64[uv_index * 2 + 1];

        //mesh->vertices[i].uv.x = 1- uv_property->array.real64[uv_index2 * 2 ];
        //mesh->vertices[i].uv.y = 1- uv_property->array.real64[uv_index2 * 2 + 1];

        //mesh->vertices[i].uv.x =  1- uv_property->array.real64[uv_index3  * 2];
        //mesh->vertices[i].uv.y = 1 - uv_property->array.real64[uv_index3  * 2 + 1];

    }
}

#define COPY_VERTICES_TO_MESH_FROM_FBX_PROPERTY_ARRAY(mesh, vertex_property, pointer_name, uv_property, uv_index_property) \
                for (u32 i = 0; i < mesh->vertex_count; i++) { \
                    mesh->vertices[i].position.x = static_cast<float32>(vertex_property->array. ## pointer_name ##[i * 3]); \
                    mesh->vertices[i].position.y = static_cast<float32>(vertex_property->array. ## pointer_name ##[i * 3 + 1]); \
                    mesh->vertices[i].position.z = static_cast<float32>(vertex_property->array. ## pointer_name ##[i * 3 + 2]); \
                } \

void Fbx_Binary_File::fill_out_mesh(Triangle_Mesh *mesh)
{
    Fbx_Node *vertices = find_node("Vertices");
    Fbx_Node *indices = find_node("PolygonVertexIndex");
    Fbx_Node *normals = find_node("Normals");
    Fbx_Node *uv =  find_node("UV");
    Fbx_Node *uv_indices =  find_node("UVIndex");

    if (!vertices || !indices || !normals || !uv || !uv_indices) {
        print("Some mesh data from the fbx file for the triangle mesh wasn't found");
        return;
    }

    Fbx_Property *vertex_property = vertices->properties[0];
    Fbx_Property *index_property = indices->properties[0];
    Fbx_Property *normal_property = normals->properties[0];
    Fbx_Property *uv_property = uv->properties[0];
    Fbx_Property *uv_index_property = uv_indices->properties[0];

    if (vertex_property->type != PROPERTY_TYPE_VALUE_ARRAY || index_property->type != PROPERTY_TYPE_VALUE_ARRAY) {
        print("Vertex fbx property of index fbx property doesn't appropriate array type");
        return;
    }

    assert(vertex_property->array.count / 3 != 0);
    mesh->allocate_vertices(vertex_property->array.count / 3);

    switch (vertex_property->value_type) {
        case PROPERTY_VALUE_TYPE_REAL32: {
            COPY_VERTICES_TO_MESH_FROM_FBX_PROPERTY_ARRAY(mesh, vertex_property, real32, uv_property, uv_index_property);
            break;
        }
        case PROPERTY_VALUE_TYPE_REAL64: {
            //COPY_VERTICES_TO_MESH_FROM_FBX_PROPERTY_ARRAY(mesh, vertex_property, real64, uv_property, uv_index_property)
            copy_fbx_mesh_data_to_triangle_mesh(mesh, vertex_property, uv_property, uv_index_property);
            break;
        }
        case PROPERTY_VALUE_TYPE_S32: {
            COPY_VERTICES_TO_MESH_FROM_FBX_PROPERTY_ARRAY(mesh, vertex_property, int32, uv_property, uv_index_property)
            break;
        }
        case PROPERTY_VALUE_TYPE_S64: {
            COPY_VERTICES_TO_MESH_FROM_FBX_PROPERTY_ARRAY(mesh, vertex_property, int64, uv_property, uv_index_property)
            break;
        }
    }

    // Here i map uv coordinates on a mesh
    for (int i = 0; i < index_property->array.count; i++) {
        s32 index;
        s32 uv_index = uv_index_property->array.int32[i];
        if (index_property->array.int32[i] < 0) {
            index = (index_property->array.int32[i] * -1) - 1;
        } else {
            index = index_property->array.int32[i];
        }

        mesh->vertices[index].uv.x = uv_property->array.real64[uv_index * 2];
        mesh->vertices[index].uv.y = uv_property->array.real64[uv_index * 2 + 1];
        Vector3 * pos = &mesh->vertices[index].position;
        print("[{}] Vertex: x {} y {} z {},    Vertex index {}, UV x {}, y {},    UV_index {}", i, pos->x, pos->y, pos->z, index, mesh->vertices[index].uv.x, mesh->vertices[index].uv.y, uv_index);
    }

    if (index_property->array.int32[2] < 0) {
        mesh->allocate_indices(index_property->array.count);
        u32 triangle_index_count = mesh->index_count / 3;
        for (int i = 0; i < triangle_index_count; i++) {
            mesh->indices[i * 3]  = index_property->array.int32[i * 3];
            mesh->indices[i * 3 + 1] = index_property->array.int32[i * 3 + 1];
            mesh->indices[i * 3 + 2] = (index_property->array.int32[i * 3 + 2] * -1) - 1;

        }
    } else if (index_property->array.int32[3] < 0) {
        mesh->allocate_indices((index_property->array.count / 4) * 6);
        int k = 0;
        s32 quard_index_count = mesh->index_count / 4;
        for (int i = 0; i < quard_index_count; i++) {
            s32 first_index  = index_property->array.int32[i * 4];
            s32 second_index = index_property->array.int32[i * 4 + 1];
            s32 thrid_index  = index_property->array.int32[i * 4 + 2];
            s32 fourth_index = (index_property->array.int32[i * 4 + 3] * -1) -1;

            if (k < mesh->index_count) {
                mesh->indices[k] = first_index;
                mesh->indices[k + 1] = second_index;
                mesh->indices[k + 2] = thrid_index;

                mesh->indices[k + 3] = thrid_index;
                mesh->indices[k + 4] = fourth_index;
                mesh->indices[k + 5] = first_index;
                k += 6;
            }
        }
    }
    //for (int i = 0; i < mesh->index_count; i++) {
    //  s32 index = mesh->indices[i];
    //  s32 uv_index = uv_index_property->array.int32[i];
    //  mesh->vertices[index].uv.x = uv_property->array.int32[uv_index];
    //  mesh->vertices[index].uv.y = uv_property->array.int32[uv_index + 1];
    //}
}

char *Fbx_Binary_File::get_texture_name()
{
    Fbx_Node *texture_name = find_fbx_node(&root_nodes, "TextureName");
    if (!texture_name) {
        //@Note: here need to be warning message.
        return NULL;
    }
    Fbx_Property *property = texture_name->properties[0];

    if (property->is_property_type_value() && property->is_property_value_type_string()) {
        Array<char *> buffer;
        split(property->value.string, "::", &buffer);
        return _strdup(buffer[1]);
    }
    //@Note: here need to be warning message.
    return NULL;
}

```

I have tried to use fbx sdk and i wrote code like in the first answer on the question Importing and Displaying .fbx files. I also get the same data like in my written code.

# Answer
Consider the coordinate system that you are using. You can use a tool in Maya called "Game Exporter" this ensures that the Y coordinate is upwards and UV coordinates are in XY directions. Also, make sure that you are exporting the UV coordinates in the fbx file. Also, the v direction may be flipped, try 1-v instead of v.
> 0 votes

---
Tags: textures, uv-mapping, fbx
---


# Question
Title: Performance of many canvas drawImage calls is very slow
I'm developing a top-down 2D tile-based canvas game. I have a single sprite sheet of all my tiles, and then a JSON tile map array of where they're placed.

Previously I would render all the layers of tiles out to a single canvas element once, and then re-render that every frame. This would give me 300+ FPS because it would just be a single draw call each frame to redraw this canvas.

However, the issue with this is that the map is not just a "flat" image. Sometimes tiles need to be destroyed, or sometimes the player needs to stand behind certain tiles (such as when the player is above them), which doesn't seem possible if the map is just a static image.

As a result, I believe I instead need to re-render all the tiles every frame. However, even if I only re-render the tiles that the user can see, the FPS drops tremendously. With just two tile layers and a 100x100 map, the FPS drops to 20.

I would have assumed that, despite there being 100 * 100 * 2 `canvas.context.drawImage` calls per frame, that it would still be fine, because it was leveraging the GPU, and I'm using a single sprite sheet, so there should be no texture swapping. Apparently this is not the case.

I was looking for a way to possibly speed this up, but the recommendations seem to be extremely heavy-handed and opinionated libraries like three.js and pixi.js. These libraries would be great, except they do too much. In PIXI and Three.js you need to add objects to a scene and they're automatically redrawn each frame. This is not what I need, as my current ECS architecture demands an immediate-mode renderer, and I have my own scene graph already, so I can't (and don't want to) use theirs.

Is there a solution here? The only thing I really need to do is draw images clipped from a spritesheet quickly. Can this be done using immediate-mode rendering? Or is it doomed to be 20 FPS?

# Answer
> 2 votes
Even though the map is "small" at 100x100 with two layers, that's still 20,000 draw calls per frame.

One optimization is to only draw the tiles that are visible such as limiting your camera's viewable area and zoom levels so you can't see more than a few hundred tiles at once. You'll have to implement the ability to query if a tile is visible to the camera though.

A second optimization (after the above is implemented) is to group the visible tiles into one big draw call.

# Answer
> 0 votes
What do you think about rendering 2-3 states of the game world? Like, one which is "the stuff below the player", another which is "the stuff above the player", and more to suit your needs. Then simply render these in their respective order `stuff below player -> player -> stuff above player`

Then instead of re-collecting the image data every time a modification is made to the game world, perhaps there's another solution where you can manually edit the image's `imageData` object using math to near-instantly hunt down the exact pixels which need updating? This part is a bit fuzzy, but perhaps you could make it work? (Resulting in 2-3 calls to the renderer every frame, and a single one-tile-wide edit to image data every time a world-changing action is taken)

---
Tags: 2d, shaders, javascript, html-canvas, webgl
---


# Question
Title: Predicting trajectory of Box2D physics body using both: linear dumping and gravity
I would like to calculate position of physics body after some time because of predicting shots trajectory in my game.

I found some great answer here where Iter Ator provides equation to calculate actual velocity of body after time, provided time, starting velocity and linear dumping but no gravity. I was able to integrate this solution to get distance traveled in time equation. Problem is that this doesnt take gravity into account.

There is also this tutorial that has many information about predicting physics body trajectory but doesnt take linear dumping into account at all.

What I would love to have is combined single equation that covers both linear dumping AND gravity to predict Box2d physics body actual velocity/position but math is too hard for me :(.

Problem seems to be that physics body velocity is both accelerated by gravity and dumped at the same time.

# Answer
All the equations are in a frame with the y axis vertical pointing upwards and the x axis horizontal pointing in the initial direction of the movement.
The position is noted \\$ (x;y) \\$, the speed is \\$ (\dot{x};\dot{y}) \\$ and their initial values at \\$ t = 0 \\$ are respectively \\$ (x\_0;y\_0) \\$ and \\$ (\dot{x}\_0;\dot{y}\_0) \\$.

Your projectile undergoes the action of two forces:

* its own weight, always oriented towards the ground: \\$ \vec{W} = -mg. \vec{y} \\$
* the friction from the air (drag), opposing the direction of motion and assumed linear: \\$ \vec{F} = -k. \vec{v} \\$

Newton's second law gives us:
\\$ m \ddot{x} = -k \dot{x} \\$ (1)
\\$ m \ddot{y} = - k \dot{y} \ - \ mg \\$ (2)

(1) can be integrated once to give a first order ODE that we can solve:
\\$ m \dot{x} = -kx \ + \ D \Rightarrow \dot{x} = -\frac{k}{m} x \ + \ \frac{D}{m}\\$ where \\$ D \\$ is the integration constant. \\$ x(t) = C e^{-\frac{k}{m}t} + \frac{D}{k} \\$ with \\$ C = -\frac{m}{k} \dot{x}\_0 \\$ and \\$ D = k x\_0 + m \dot{x}\_0 \\$

(2) In is a second order non-homogeneous ODE, skipping some steps, the solution is:
\\$ y(t) = y\_0 \ + \ \frac{m}{k} \dot{y}\_0 \ - \ \frac{m}{k} \dot{y}\_0 e^{-\frac{k}{m} t} - mgt \\$

You can get the velocity equations by derivating the position equations.
I've only included very minimal details, I can expand some steps if needed.
> 1 votes

---
Tags: c++, 2d, physics, box2d
---


# Question
Title: Transactions on lists of coins of different values
For learning purposes, I am developing the first steps of an idle game with exponentially higher income numbers. Usual int, long, etc. can't store big enough numbers for that.

I looked through many threads which I found on google and using a list (or an array) which is separated in e.g. bronze coins, silver coins, gold coins, etc. seems to be the cleanest version.

In my first approaches I created this list:

```
namespace Coins
{
    public class script_coinHandler : MonoBehaviour
    {
        public List<Coin> coinList = new List<Coin>() // list based on the "Coin" class
        {
            new Coin() { Name = "bronze"},
            new Coin() { Name = "silver"},
            new Coin() { Name = "gold"},
            new Coin() { Name = "diamond"},
        };
    }

    public class Coin
    {
        public string Name { get; set; }
        public int Amount { get; set; }
        public int Multiplier { get; set; }
    }

}

```

I want each coin type to go up to 999999. This means 1 silver = 1000000 bronze, 1 gold = 1000000 silver.

I can't get my head around a way to do maths with this list. Example:

**Player** has 3000 GOLD, 320000 SILVER, 524321 BRONZE

**Player** wants to buy something for 20 GOLD, 120000 SILVER, 300000 BRONZE

Just subtracting 20 from GOLD, 120000 from SILVER, and 300000 from BRONZE won't always work. For example when a Player has no BRONZE but some SILVER - you can't subtract 300000 BRONZE without converting SILVER to BRONZE first.

**Q:** What would be an efficient function to subtract the price from the total amount? What about multiplying and dividing? Accuracy is not important. When spending a few GOLD, nobody will care about 10000 BRONZE.

# Answer
I would internally represent all money values in the game in bronze coins, and then do the conversion to the diamond/gold/silver/bronze representation only when presenting values on the UI. That makes a lot of things a lot easier for you, notably doing arithmetic with money.

Unfortunately the number range you need goes up to 10^24, which does not fit into a `long` (64 bit integer). But you can solve that problem by using the type `BigInteger`. It can handle integer values of practically unlimited size. It supports all the C# standard math operators like `+` or `*`.

When you want to initialize a BigInteger with a value which is too large to be represented by a `long`, then create a string representation of that value and use `BigInteger.Parse(bronzeValueAsString)`.

**Edit:** A comment asked for performance. So I wrote a script which takes a 44 digit number and calculates the hailstone sequence from it, a simple but neat number crunching algorithm combining multiplication, division, addition and odd/even checks. And I even used a BigInteger for the loop counter, which would not even have been necessary in this case.

```
using UnityEngine;
using System.Numerics;

public class BigIntegerHailstone : MonoBehaviour
{
    void Update()
    {
        BigInteger current = BigInteger.Parse("9999999999999999999999999999999999999999999");
        BigInteger count = BigInteger.Zero;
        while (current != BigInteger.One) {
            count++;
            if (current.IsEven) {
                current /= 2;
             } else {
                 current = current * 3 + 1;
             }
        }
        Debug.Log(count);
    }
}

```

The number of loop-iterations for that number is 1402. A scene with this script on an object ran with ~500 FPS on my machine (Core i5-6600). The profiler says this took under 1.6 millisecond to calculate:
> 3 votes

# Answer
Here's how we could do this with lists of integers representing the number of coins of each denomination held, added, or required for the price, in ascending order of value. These are effectively digits in a base-one-million number. Where we're not holding any coins of a particular denomination, or a price/increment does not include any coins of that denomination, we store a zero. We can omit zeroes for denominations above and beyond the value we're representing.

So the list `{1, 0, 3}` means "1 Bronze coin, 0 Silver coins, 3 Gold coins, no Diamonds or higher"

I also assume that the inputs/inventory are always expressed in "lowest terms" — so you never have a price of 2 million Bronze coins, instead that would be represented as 2 Silver coins and 0 Bronze coins.

The version below is not thread-safe, so if you want to interact with the player's purse over multiple threads, you'll want to add some locks or more sophisticated transaction handling.

```
// You could also make this a lookup table with distinct values at each denomination.
const int COIN_STEP_SIZE = 1000000;

// Number of each coin held, in order from least to most valuable coin type.
// Intermediate coins you lack are present as placeholder 0 values.
List<int> _inventory = new List<int>();

// Scratch pad for transactions.
Stack<bool> _borrow = new Stack<bool>();

// Deduct the money only if we can afford it, otherwise do nothing.
// Report back whether the transaction was successful.
public bool TryDeduct(List<int> price) {
    if (CanAffort(price)) {
        DeductWithLoggedBorrows(price);
        return true;
    }

    return false;
}

// Check if we can pay the price, without mutating the inventory.
public bool CanAfford(List<int> price) {
    // Clear our scratch pad.
    _borrow.Clear();

    // Initialize the scratch pad with a guard value.
    // "We have not borrowed any Bronze coins from lower denominations" (there are none)
    _borrow.Push(false);

    // Iterate over the price, from lowest to greatest value coin denominations.
    for (int denomination = 0; denomination < _inventory.Count; denomination++) {
        // If we had to borrow from this coin to pay the previous one, add one to the price.
        int required = borrow.Peek() ? 1 : 0;

        // Coins above the top end of the price are treated as zero price.
        if (denomination < price.Count) required += price[denomination];

        // If we don't have enough of this coin, log a borrow from the next.
        if (_inventory[denomination] < required) {
            _borrow.Push(true);
        } else {
            // Otherwise, if we've handled all the coins in the price,
            // we know we can afford this!
            if (denomination >= (price.Count - 1)) return true;

            // Or, we log "no borrow from next required" and continue.
            _borrow.Push(false);
        }
    }

    // We still had more to borrow when we hit the end of the player's inventory,
    // so we cannot afford this.
    return false;
}

// Mutate the inventory, only after we've determined that we can afford it,
// and logged where we need to do borrowing.
private void DeductWithLoggedBorrows(List<int> price) {
    // Start at the top denomination we had to check to pay the price,
    // and work our way back down to the lowest denomination.
    for (int denomination = _borrow.Count - 1; denomination >= 0; denomination--) {
        bool borrow = _borrow.Pop();

        int required = borrow ? 1 : 0;
        if (denomination < price.Count) required += price[denomination];

        inventory[denomination] -= required;

        // If we borrowed here, add the change to the denomination below.
        // (This will never go out of bounds because we initialize the stack with false)
        if (borrow) inventory[denomination - 1] += COIN_STEP_SIZE;
    }
}

public void Add(List<int> coins) {
    int carry = 0;
    int denomination;
    for (denomination = 0; denomination < coins.Count; denomination++) {
        _inventory[denomination] += coins[denomination] + carry;

        if (_inventory[denomination] >= COIN_STEP_SIZE) {
            carry = _inventory[denomination] / COIN_STEP_SIZE;
            _inventory[denomination] -= carry * COIN_STEP_SIZE;
        } else {
            carry = 0;
        }
    }

    while (carry > 0) {
        _inventory[denomination] += carry;

        if (_inventory[denomination] >= COIN_STEP_SIZE) {
            carry = _inventory[denomination] / COIN_STEP_SIZE;
            _inventory[denomination] -= carry * COIN_STEP_SIZE;
        } else {
            carry = 0;
        }
    }
}

```
> 2 votes

---
Tags: unity, c#, mathematics
---


# Question
Title: NullReferenceException in reticle color change script while cycling through children
I could really use another set of eyes on this. I am running into this error: NullReferenceException: Object reference not set to an instance of an object I can't figure out.

In the script below. I've verified I'm cycling through the children well enough, and I thought I assigned them an appropriate object but for some reason only the first child of the selected reticle is turning red, and the following children are throwing the errors.

This is my Reticle Setup:

Each reticle group has a various number of objects with an Image component that make up a reticle. I turn on and off each reticle group depending on what fire button is being pressed, and return to default if none are pressed. On top of that the reticles are Red or White depending on if the WeaponManager says its a valid target or not.

These two lines in the script below are throwing the errors.

```
childGameObject2.GetComponent<Image>().color = Color.white;

```

```
childGameObject1.GetComponent<Image>().color = Color.red;

```

Whole reticle script:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class reticle : MonoBehaviour
{

    [SerializeField] private GameObject defaultReticle;
    [SerializeField] private GameObject machineGunReticle;
    [SerializeField] private GameObject rocketLauncherReticle;

    private int reticleSelect;
    private int fireOneSelect;
    private int fireTwoSelect;
    private int utilitySelect;

    private Transform childGameObject1;
    private Transform childGameObject2;

    // Start is called before the first frame update
    void Start()
    {
        // remove mouse cursor
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;

        defaultReticle.SetActive(true);
        reticleSelect = 1;

    }

    // Update is called once per frame
    void Update()
    {
        // update weapon selections from WeaponManager.cs
        fireOneSelect = WeaponManager.fireOneSelect;
        fireTwoSelect = WeaponManager.fireTwoSelect;
        utilitySelect = WeaponManager.utilitySelect;

        // toggle locked and free aim
        if (Input.GetKey(KeyCode.Tab))
        {
            if (Cursor.lockState == CursorLockMode.Locked)
            {
                Cursor.lockState = CursorLockMode.Confined;
            }
            else
            {
                Cursor.lockState = CursorLockMode.Locked;
            }
        }

        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Cursor.visible = true;
        }

        if (WeaponManager.eligibleTarget == false)
        {
            // handle out of range reticle color changes
            for (int i = 0; i < gameObject.transform.childCount; i++)
            {
                if (gameObject.transform.GetChild(i).gameObject.activeSelf == true)
                {
                    Debug.Log(gameObject.transform.GetChild(i).name);
                    // cycle through all reticle children and turn them red
                    for (int g = 0; g < gameObject.transform.GetChild(i).gameObject.transform.childCount; g++)
                    {
                        childGameObject1 = gameObject.transform.GetChild(i).gameObject.transform.GetChild(g);
                        Debug.Log(childGameObject1.name);
                        //LINE BELOW CAUSING ISSUE WHEN NOT ELIGIBLE TARGET
                        childGameObject1.GetComponent<Image>().color = Color.red;
                    }
                }
            }
        }
        else if (WeaponManager.eligibleTarget == true)
        {
            // handle out of range reticle color changes
            for (int m = 0; m < gameObject.transform.childCount; m++)
            {
                if (gameObject.transform.GetChild(m).gameObject.activeSelf == true)
                {
                    Debug.Log(gameObject.transform.GetChild(m).name);
                    // cycle through all reticle children and turn them red
                    for (int h = 0; h < gameObject.transform.GetChild(m).gameObject.transform.childCount; h++)
                    {
                        childGameObject2 = gameObject.transform.GetChild(m).gameObject.transform.GetChild(h);
                        Debug.Log(childGameObject2.name);
                        //LINE BELOW CAUSING ISSUE WHEN ELIGIBLE TARGET
                        childGameObject2.GetComponent<Image>().color = Color.white;
                    }
                }
            }
        }

        // decide if firing reticle is needed or show default reticle
        // reticleSelect values
        // 1 = default
        // 2 = fireOne
        // 3 = fireTwo
        // 4 = utility
        if (Input.GetButton("Fire1"))
        {
            reticleSelect = 2;
        }
        else if (Input.GetButton("Fire2"))
        {
            reticleSelect = 3;
        }
        else
        {
            reticleSelect = 1;
        }

        // reset reticles to inactive to simplify code below
        for (int k = 0; k < gameObject.transform.childCount; k++)
        {
            gameObject.transform.GetChild(k).gameObject.SetActive(false);
        }

        // handle reticle switch logic
        if (reticleSelect == 1)
        {
            // handle default reticle
            defaultReticle.SetActive(true);
        }
        else if (reticleSelect == 2)
        {
            // handle fire one reticles
            switch (fireOneSelect)
            {
                // 1 = machineGun
                // 2 = na
                // 3 = na
                case 1:
                    machineGunReticle.SetActive(true);
                    break;
                case 2:
                    //newReticle.SetActive(true);
                    break;
                case 3:
                    //newReticle.SetActive(true);
                    break;
                default:
                    defaultReticle.SetActive(true);
                    break;
            }
        }
        else if (reticleSelect == 3)
        {
            // handle fire two reticles
            switch (fireTwoSelect)
            {
                // 1 = rocketLauncher
                // 2 = grenadeLauncher
                // 3 = na
                case 1:
                    rocketLauncherReticle.SetActive(true);
                    break;
                case 2:
                    //grenadeLauncher.SetActive(true);
                    break;
                case 3:
                    //newReticle.SetActive(true);
                    break;
                default:
                    defaultReticle.SetActive(true);
                    break;
            }

        }
        transform.position = Input.mousePosition;
    }

}

```

On a separate note, this bit of code seems incredibly inefficient to turn off all reticles each update before activating the chosen one, but its a lot cleaner than adding all the inactivate lines in the switch statement below that. How would one go about turning them on and off with less code?

```
// reset reticles to inactive to simplify code below
for (int k = 0; k < gameObject.transform.childCount; k++)
{
   gameObject.transform.GetChild(k).gameObject.SetActive(false);
}

```

# Answer
Are you sure that Left Marker has an Image component? Double check it, looks like it is the only game object that is problematic.

As for the for loop it looks like you could remove the code after the loop and replace it with something that would immediately switch between active and inactive based on the reticleSelect value (just make sure the indexes match when you set reticleSelect).

```
// activate or deactivate reticles based on user input
for (int k = 0; k < gameObject.transform.childCount; k++)
{
   gameObject.transform.GetChild(k).gameObject.SetActive(k == reticleSelect);
}

```
> 1 votes

---
Tags: unity, ui-design, unity-ui
---


# Question
Title: Angle between start and current rotation
I'm facing problem of the operations on rotations. I have a wheel with a start rotation of (0, 0, 0). The player has to rotate wheel 270 degrees in Y axis either left or right.

During the rotation slider should indicate progress of the rotation. For example if player rotated 135 degrees in right direction, slider is 50% filled to the right.

The thing is that I'm not sure how to get the value of which the player rotate the object. For example when I start rotating right my angle changes from (0, 0, 0) to (0, 359, 0). How can I resolve this issue so it knows that change from (0, 0, 0) to (0, 359, 0) means player rotated only +1 degree?

# Answer
We can keep track of how many quarter-turns we've travelled, counter-clockwise from the start angle (this can go negative for clockwise turns). Then we can measure our current angle relative to the last quarter-turn milestone we crossed.

Because that milestone is never more than 90 degrees away from our angle last frame, we can move just shy of 90 degrees further in a single step and still unambiguously find the total rotation travel.

Then we can update the number of quarter-turns if we've crossed into a new quadrant.

```
public Transform wheel;

public float totalAngle;

float _startAngle;
int _quarterTurns = 0;

void Start() {
    _startAngle = wheel.eulerAngles.z;
}

void Update() {
    float currentAngle = wheel.eulerAngles.z;

    // Compute the total angle at the last milestone.
    float milestoneAngle = _startAngle + _quarterTurns * 90;

    // Get the shortest signed difference from the last milestone (-180 to 180)
    float fromMilestone = Mathf.DeltaAngle(milestoneAngle, currentAngle);

    // Our total angle is the sum of the last milestone and our deviation from it.
    totalAngle = milestoneAngle + fromMilestone;

    // If we've crossed another 90-degree increment, update our milestone for next frame.
    if (Mathf.Abs(fromMilestone) >= 90) {
        _quarterTurns += Mathf.RoundToInt(fromMilestone)/90;
    }
}

```
> 0 votes

---
Tags: unity, mathematics, rotation, quaternion
---


# Question
Title: What is the best way to "carve" a terrain created from a heightmap?
I have a `3d landscape` created from a `heightmap`. I'd like to "carve" some holes in that terrain. That will allow me to create bridges, caverns and tunnels inside it.

That operation will be done in the game editor so it doesn't need to be realtime. In the end, rendering is done using traditional polygons.

**What would be the best/easiest way to do that ?** I already think about several solutions :

**Solution 1**

1) Create voxels from the `heightmap` (very easy). In other words, fill a 3D array like this : `voxels[32][32][32]` from the `heightmap` values.

2) Carve holes in the voxels as i want (easy too).

3) Convert voxels to polygons using some `iso-surface extraction` technique (like `marching cubes`).

4) Reduce (decimate) polygons created in 3).

This technique seems to be the most promising for giving good results (untested). However the problem with `marching cubes` is that they tends to produce lots of polygons thus reducing them is mandatory. Implementing 4) also seems not trivial, i have read several papers on the web and it seems pretty complex. I was also unable to find an example, code snippet or something to start writing an algorithm for triangle mesh decimation. Maybe there is a special decimation algorithm (simpler) for meshes created from `marching cubes` ?

**Solution 2**

1) Create some triangle mesh from the heighmap (easy).

2) Apply severals 3D boolean operation (eg: subtraction with a sphere) to carve the mesh.

3) apply some procedure to reduce polygons (optional).

Operation 2) seems to be very complex and to be honest i have no idea how to do that. Also applying many boolean operation seems to be slow and will maybe degrade the triangle mesh every time a boolean operation is applied.

# Answer
3D carving can be done with Surface extraction of a 3D density field. Then you can reduce the values in the density field and so you can carve your hole. Examples for this are marching cubes, or dual contouring. The problem is that heightmap polygons and polygons generated with surface extraction are not that easy to mix together. Either you only use surface extraction or you invent some technique that helps you to merge them together.
> 1 votes

# Answer
> That operation will be done in the game editor

Did you just imply that you're expecting to make something better than world-class modelling application developers? Not that I don't consider all this doable, it's just time-consuming and will most likely require an artistic touch in the end anyway (which procedural generation tools simply cannot provide from that point in the pipeline). Especially since you haven't considered texcoord generation here *at all*.

So before I make my suggestion, let me point you to someone who struggled with a similar problem: Art Asset Overview #32 (from Wolfire Blog). They solved it by allowing to edit the procedurally generated terrain mesh. If you check their blog, they've done really impressive things like making crazy algorithms work (Delaunay triangulation is extremely crazy because of floating point number inexactness, for example).

So we've come full circle back to my suggestion. It's quite simple, actually.

1. Find yourself a good terrain generator for the base terrain.
2. Find or create something that would generate a mesh from a heightmap.
3. Find a good modelling application with sculpting tools that you like. If necessary, create converters between yours and whatever the modelling application can import/export.
4. Render the mesh in your game and use your editor for nothing more than selecting a mesh.

If you want, you can easily split the mesh into many smaller meshes for culling. As opposed to what you want to do up there, it's much easier.
> 0 votes

# Answer
If you have a heightmap that is, say, 512x512 and reinterpret it as a volume of 512x512x512, with every voxel set to a value of 0 that would be in the terrain, marching cubes should give you a similar result on this than what you would get when building a regular heightmap terrain. In order to get closer to the proper heightmap, you can use a more accurate representation. So instead of just setting everything to 0, you have to set it to values that represent the actual height for this voxel, as otherwise, you only have 512 different height positions which would look bad.

This means that all you have to implement is marching cubes, as well as the heightmap =\> voxel transfer. These are all fairly simple things, just marching cubes is like one huge collection of if/else or switch. One problem you will get is of course the resolution. You can however likely have a much smaller vertical resolution (I'd try to get square voxels) because your terrain is probably much wider than it is high, which should alleviate the problem. Otherwise you have to tile the terrain into multiple chunks and only keep the chunk in memory during editing that you are working on.

At runtime you then just have a mesh. And if you chunked the volume texture, you also have something to work with for larger scenes. You could also compute a LOD hierarchy from this by downsampling the volume and running marching cubes again.

Honestly, the HARD part is writing the tools that actually allow you to carve in a usable way. All you have to do is set voxels to 1 instead of 0, but developing a good user interface for this isn't trivial. Also, running marching cubes on the whole volume every time something is edited is probably kinda slow and could be improved somehow.
> 0 votes

---
Tags: c++, 3d, procedural-generation, terrain, heightmap
---


# Question
Title: It is possible to process data on relay servers?
I have a small game engine done in Java, and re-creating it on C++. While re-creating it i've decided on adding basic p2p online multiplayer. However, after reading more about networking, there are multiple models, and the Client-server host with relay model seems attractive, since it overcomes most of NAT issues of port fowarding and does not expose players public IP.

My point is - can a relay server be used to do some minimal data processing? The goal is not to use a dedicated, full featured server application, but just do minimal calculations on the data to detect some basic cheats.

For example: Preventing internal speed hacks by sending the system timestamp every 60 cycles, and then the relay would store the previous time stamp and compare the next one, if the time difference is less than 1000ms, disconnect the player.

# Answer
> 0 votes
There actually are SaaS providers who lease off-the-shelf relay server solutions to you. Photon or Playfab, for example. How much custom server-sided logic you can implement on those solutions depends on the product. But as usual with other people's software running on other people's servers (or "the cloud" how the marketing people call it): There are limits to how much you can customize them, and when you need to exceed these limits, you are out of luck.

But you can of course also develop your own relay server application from scratch. That way it's your decision where you want to place it on the sliding scale between a dumb relay and authoritative gameserver.

The most simple solution would be a relay which just forwards network messages without even looking at them. This is quick to develop and inexpensive to host, but very insecure when it comes to cheat prevention.

The other extreme would be a a full-fledged authoritative gameserver which checks every single incoming messages for whether or not that player can do that right now, calculates all game mechanics server-sided, and sends out the results of these calculations to only those client which are supposed to know about them. When you do this properly, then its very design makes any cheat impossible except for purely client-sided automation. But creating a server like that takes a lot of time, adds a lot of complexity to your network stack and makes your server computationally expensive, which drives up your hosting cost (but might actually reduce your network traffic cost due to server-sided censoring of hidden information).

Most online multiplayer games are somewhere between those two extremes.

---
Tags: c++, java, networking, software-engineering, peer-to-peer
---


# Question
Title: How does the InsideTessFactor affect points of a triangle in a DirectX11 domain shader?
I found this example in this Chinese language document.

In the image above, I can understand the value of `SV_TessFactor` because for every side of this triangle, there are `4,1,6` line segments respectively. But I don't understand how `InsideTessFactor` is 5.

There are 12 points and 12 line segments inside the triangle. It seems to me that 12 is not relevant to 5.

# Answer
You can understand this as a continuation of the two preceding diagrams in the document you linked:

For an inside tesselation factor **n**, we first imagine that each of the sides of the outside triangle have been subdivided into **n** segments.

Then we draw a perpendicular up from each of the newly-added vertices. Where the two perpendiculars closest to a corner intersect, we place the corners of our next inner triangle (blue).

The other perpendiculars add vertices where they cross this triangle's sides. That means that for a triangle tessellated by a factor of **n**, this inner triangle has **n - 2** segments along each side.

Then we repeat to make a nested inner triangle (or point), until we have no more vertices in the middle of a subdivided edge to draw perpendiculars from.

So when the inside tessellation factor is 5, that first inner triangle in blue has **5 - 2 = 3** segments along each side.

You'll note this inner 3-segment triangle for the 5 case in my diagram matches the 3-segment inner triangle in your question. All that differs are the number of segments on the outer triangle's sides, controlled by the other tessellation factors.
> 1 votes

---
Tags: directx, directx11, tessellation, hull-shaders, domain-shaders
---


# Question
Title: Build and Run results in an empty window
Out of nowhere my builds are broken. The .exe just always gives me this little blank window but it runs fine in the editor.

Here are some things I have tried:

* Deleted the previous build files
* Deleted the Library folder
* Upgraded to 2020.2.4f1
* Uninstalled/Reinstalled Unity
* Deleted AppData Files
* Deleted branch and pulled it back down (the branch works fine for other people)

Here are my resolution and presentation settings:

# Answer
I was eventually able to solve this issue by clearing the project settings folder in the project. After doing that and setting my scenes back up in the build settings, things seems to work. I kept my TagManager.asset file just so I didn't lose sorting layers, etc.
> 0 votes

---
Tags: unity
---


# Question
Title: Getting path of right click in unity 3D editor
I want to create an extension for the Unity 3D Editor and have an custom asset type. During the process of creation this I recognized that I would improve the UX/usability if I can specify the path where I want to create the asset by using right click. But I fail to get the context path of the right click and I cannot find any hints on google or at the unity scripting api. Below you can see an image of the process I tried to describe above.

Here is the code that is responsible for handling the context creation "event".

```
[MenuItem("Assets/Create/Chat")]
public static void createChatViaMenu() {
    Chat c = Chatter.createDefaultChat();

    // This is the part where I want to insert the relative path.
    AssetDatabase.CreateAsset(c, "Assets/" + c.Title + ".asset");
}

```

If you need any more information please let me know.

# Answer
You can get the path by using Selection.activeObject. Here is a small code to get this feature working :)

```
   string path = AssetDatabase.GetAssetPath (Selection.activeObject);

    if (path == "")
    {
        path = "Assets";
    }
    else if (Path.GetExtension(path) != "")
    {
        path = path.Replace(Path.GetFileName (AssetDatabase.GetAssetPath (Selection.activeObject)), "");
    }
    AssetDatabase.CreateAsset (asset, AssetDatabase.GenerateUniqueAssetPath (path + "/New MyAsset.asset"));

```
> 2 votes

# Answer
### Use built-in property

If your asset is simple and doesn't need special treatment, you should use **built-in property** to generate a "create asset" menu.

```
[CreateAssetMenu( menuName = "Wappen Asset/WaveBankData" )]
public class WaveBankData : ScriptableObject
{

```

And it will magically added to right click menu -\> Create. Has same functionality as Unity's one. It will be created in current browser location, prompt for a rename, etc.

---

### Via MenuItem callback

If you really want to use customized **MenuItem**. Here is how TextMesh pro determine current right-click folder. If you call `Selection.assetGUIDs` under MenuItem callback, it will guarantee current displaying folder (the one that you clicked on its empty space)

For full script, see your own `\Packages\com.unity.textmeshpro\Scripts\Editor\TMP_ColorGradientAssetMenu.cs`

```
    [MenuItem("Assets/Create/TextMeshPro/Color Gradient", false, 115)]
    public static void CreateColorGradient(MenuCommand context)
    {
        string filePath;

        if (Selection.assetGUIDs.Length == 0)
            filePath = "Assets/New TMP Color Gradient.asset";
        else
            filePath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);

```

---

### (BONUS) The TRUE Project browser current directory

Is hidden inside internal unity `ProjectWindowUtil.TryGetActiveFolderPath` static function and needs reflector to access it. If you are coder wiz and really want to have it, here it is. (For non coder, I wont explain this, please do C# research on your own)

```
using UnityEngine;
using UnityEditor;
using System.Reflection;

    // Define this function somewhere in your editor class to make a shortcut to said hidden function
    private static bool TryGetActiveFolderPath( out string path )
    {
        var _tryGetActiveFolderPath = typeof(ProjectWindowUtil).GetMethod( "TryGetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic );

        object[] args = new object[] { null };
        bool found = (bool)_tryGetActiveFolderPath.Invoke( null, args );
        path = (string)args[0];

        return found;
    }

```

Note: tested in Unity 2019.4.19f
> 1 votes

# Answer
AFAIK, using `AssetDatabase.GetAssetPath` with `Selection` never returns a folder, instead of that always returns the last asset file you have clicked on (the one being shown in the inspector). Here is my try, in case you needed full path (but it would be easy to modify it to return a relative path):

```
private static string GetClickedDirFullPath()
{
    string clickedAssetGuid = Selection.assetGUIDs[0];
    string clickedPath      = AssetDatabase.GUIDToAssetPath(clickedAssetGuid);
    string clickedPathFull  = Path.Combine(Directory.GetCurrentDirectory(), clickedPath);

    FileAttributes attr = File.GetAttributes(clickedPathFull);
    return attr.HasFlag(FileAttributes.Directory) ? clickedPathFull : Path.GetDirectoryName(clickedPathFull);
}

```
> 0 votes

---
Tags: unity, c#
---


# Question
Title: Calculating distance in procedurally generated mesh LOD system
I'm creating a procedurally generated planet mesh based on quadtree splitting to support LOD system. I cannot find any relevant info how can I calculate distance between the camera and LOD chunks.

I have a surface view in my game where the camera is near at the planet surface and can move around the planet, it has also some zoom levels (elevation of the camera) but camera always looks in the direction to the surface like in strategy games.

**A**: Should I use simple distance calculation between the camera and the center of the chunk mesh or edge vertices of the mesh?

**B**: Is it better when I use Great-circle distance?

**C**: How should I modify the calculation when camera's elevation can be changed?

**D**: How can I determine the distance limits for each LOD level? Does it depend on the project or does it have some basics?

**Update #1**: Here is a sample when I use simple distance calculation between the center vertex of the meshes and the camera object:

* the camera is right above the point A
* point A is the center of the level 0 mesh (it is not visible because it is already divided)
* when the camera reaches the distance limit of B (which is a level 1 mesh and it is already divided in the sample) then it will be divided into four meshes where the centers are C, D, E, F
* at this time the mesh where the center point is F will be also divided because the distance of the previously generated F point is under the current LOD level minimum distance

So the base problem this: after dividing a mesh the new submeshes can be also divided because the distance is under the current LOD level minimum distance. And I think it does not work like a normal LOD system because there is a level 1 neighbour next to level 3 mesh.

**Update #2**: I tried some approaches to get the right distance calculation:

* minimum distance between the corner edges (4) and the camera
* minimum distance between the edge center vertices (4) and the camera
* minimum distance between the corner and edge center vertices (8) and the camera

Important thing: I use great-circle distance calculation.

I got wrong results using these until I created a new algorithm to define transition distance limits. Maybe it is not a very well algorithm but currently this is the most acceptable result. Here is the algorithm:

> Note: ignore the heightmap (noise) during the calculation, only a simple sphere with radius R is used
>
> 1. calculate the width of each meshes (arc length)
> 2. decrease the distance limit in each LOD level

```
float meshSphericalWidth = 2 * Mathf.PI * _shapeGenerator.Radius * (90 / (float)(CurrentLevelOfDetail + 1) / 360f);
float currentTransitionLimit = meshSphericalWidth * Mathf.Pow(0.90f, CurrentLevelOfDetail + 1);

```

After this distance calculation change I didn't notice any significant difference when I use the corner or the edge vertices to get the minimum distance. And I got this. Green is LOD1, yellow is LOD2 and red is LOD3.

It seems a good progress but we can see sometimes between two chunks the LOD level difference is 2.

Can I fix it with another distance calculation adjustments or is it a different story? I want to solve the cracks between meshes.

# Answer
I hope this solution helps others. The magically 0.90f value is just a first try, maybe it can be fine tuned.
> 0 votes

---
Tags: procedural-generation, level-of-detail, quadtree
---


# Question
Title: Method keep adding the same monster to the list
I'm creating a text based arena RPG where each day new monsters are added to a list, but with my current code, only one monster gets added to the list repeatly with the same stats (which for some reason keep increasing each day).

This method calls the creator.

```
public static List<Monster> MonsterOfTheDay()
  {
    int count = 0;
    List<Monster> MonstersListOfTheDay = new List<Monster>();

    while(count <= 5)
    {
      MonstersListOfTheDay.Add(Creator());
      count++;
    }

    return MonstersListOfTheDay;
  }

```

This is the creator

```
public static Monster Creator()
{
    Random random = new Random();
    Monster monsterChoosen = monsterListPrefab.Find(m => m.Id == random.Next(0, monsterListPrefab.Count -1));

    monsterChoosen.Level = random.Next(monsterChoosen.Level, monsterChoosen.Level + 3);

    //1Offensive, 2Defensive, 3Balance
    monsterChoosen.Type = (Types)typeList.GetValue(random.Next(1, typeList.Length));

    Console.WriteLine("Estou Aqui");

    int atributes = monsterChoosen.Level * 3;
    int spend = 0;

    Console.WriteLine("Estou Aqui");
    while(spend != atributes)
    {
      int chance = random.Next(0, 100);
      if(monsterChoosen.Type == Types.Offensive)
      {
        if(chance >= 0 && chance <= 60)
        {
          monsterChoosen.Str++;
          spend++;
        }

        if(chance >= 61 && chance <= 70)
        {
          monsterChoosen.Int++;
          spend++;
        }

        if(chance >= 71 && chance <= 85)
        {
          monsterChoosen.Agi++;
          spend++;
        }

        if(chance >= 86 && chance <= 100)
        {
          monsterChoosen.Vig++;
          spend++;
        }
      }
      else if(monsterChoosen.Type == Types.Defensive)
      {
        if(chance >= 0 && chance <= 60)
        {
          monsterChoosen.Vig++;
          spend++;
        }

        if(chance >= 61 && chance <= 70)
        {
          monsterChoosen.Str++;
          spend++;
        }

        if(chance >= 71 && chance <= 85)
        {
          monsterChoosen.Int++;
          spend++;
        }

        if(chance >= 86 && chance <= 100)
        {
          monsterChoosen.Agi++;
          spend++;
        }
      }
      else if(monsterChoosen.Type == Types.Balance)
      {
        if(chance >= 0 && chance <= 25)
        {
          monsterChoosen.Str++;
          spend++;
        }

        if(chance >= 26 && chance <= 50)
        {
          monsterChoosen.Int++;
          spend++;
        }

        if(chance >= 51 && chance <= 75)
        {
          monsterChoosen.Agi++;
          spend++;
        }

        if(chance >= 76 && chance <= 100)
        {
          monsterChoosen.Vig++;
          spend++;
        }
      }
      else if(monsterChoosen.Type == Types.Prefab)
      {
        spend++;
      }
      else
      {
        Console.WriteLine("Error");
      }
    }

    return monsterChoosen;
  }

```

# Answer
I changed the initial 3 lines of the Creator method, and now it's working properly.

```
Random random = new Random();
int randId = random.Next(2);

Monster monsterChoosen = new Monster(monsterListPrefab.Find(m => m.Id == randId));

```

The reason is, as Philipp said, the old code kept the information of the `monsterChoosen` variable, so it would not generate a new one when called again, keeping the same result and only increasing its stats and level. Now with the new line of the variable, `monsterChoosen` can update every time the method is called.
> 1 votes

---
Tags: c#, rpg
---


# Question
Title: How to see which mouse button was pressed (Unity Input System)
I have switched my game to use the new Unity Input System, and I want to know which mouse button was pressed when an action is called.

Here's how it's set up:

Whenever one of these three mouse buttons are pressed, the MouseButtonClicked action will fire. I want to somehow know which one of these buttons was pressed from this single action, rather than making 3 seperate actions for 3 seperate mouse buttons.

I have tried reading the values from `InputAction.CallbackContext context` but I can't seem to get a proper value from the mouse button which was pressed.

How can I do this?

# Answer
You don't.

The `InputActions` assets in the new input system are meant to create an abstraction layer between different pieces of input hardware and what actions their inputs are supposed to trigger in the context of the game.

That means Actions are meant to be semantic, not technical. You don't want to do something when the player clicked the mouse button. You want to do something when the player delivered an input with a specific meaning within the context of your game. And one way to deliver that input might be the click of a specific mouse button... and another might be a gamepad button... and another a gesture on a touchscreen.

This philosophy is reflected by the `InputValue` object passed to your event handlers which react to those actions. It only provides a value and hides the technical details of which physical part of which device provided that value.

Currently you have an action with the meaning "Mouse Button Clicked" which is triggered by three different hardware inputs, namely left-click, right-click and middle-click. This would be fine if you wanted all three mouse buttons to do the same thing, but even then you would rename that action to what you *actually* want to happen on a mouse-click.

If you want each mouse-button to perform a different kind of action, then you would create three actions named after what you actually want to do (Select, Deselect, NavigateBack, MapPanningMode, Fire, AltFire... whatever makes sense in the context of your game), and assign each mouse button to the corresponding action.

---

Yes, the new input system has a very different philosophy than you might be used to as a user of the good old hardware-oriented `Input` class (especially when you are one of the Unity developers who so far eschewed the InputManager window and preferred to work with KeyCode's instead). So when you want to use the new input system efficiently, then you need to really change the way you think about input.

But it is really worth it to give it a chance, because when you understood and internalized the way it wants you to use it, then supporting different kinds of input devices and keyboard layouts turns from a chore into a triviality.
> 3 votes

---
Tags: unity, input, events, mouse
---


# Question
Title: How to draw unity gizmos with new input system?
I am using the new Unity Input system for my game.

When I press a key, for example "Q", I want gizmos to be drawn.

However, I can't subscribe to a keypress event with a Gizmo drawing function, because it says it needs to be inside of OnDrawGizmos(). Furthermore, I can't subscribe with that function because it says it doesn't take any parameters, and I need to pass `InputAction.CallbackContext context` as a parameter, for it to be considered okay by the event system.

Here's the code for how I did it before:

```
public void OnDrawGizmos()
{
    if (Input.GetKey(KeyCode.Q))
    {
        DrawStuff();
    }
}

```

How can I recreate this?

# Answer
> 2 votes
As I explained in my answer to your previous question, you generally should try to avoid thinking of input in terms of keypresses and more in terms of semantic actions. But in this particular case you are talking about the `OnDrawGizmos` editor-feature your actual players are not going to see anyway, so it's no big deal to go for a hackish solution. The 1:1 equivalent of the above code with the new Input API would be:

```
public void OnDrawGizmos()
{
     if (Keyboard.current[Key.Q].isPressed) {
         DrawStuff();
     }
}

```

For more information:

* The Migration Guide from the old to the new input system (but keep in mind that most of the things described there are no longer best practice!)
* Documentation for `Keyboard` (which is unfortunately a total mess). `.current` is the current keyboard (the new input system API is already designed with future support for multiple keyboards in mind, but currently the engine does not support more than one)
* Documentation for `KeyControl` (which tells you what else you can do with a specific keyboard key)

---
Tags: unity, input, events, debugging
---


# Question
Title: Why when playing mixamo animation on my player the player ending and also while playing the animation inside the ground(terrain)?
The player have this components : Animator , Rigidbody , Capsule Collider , Third Person User Control , Third Person Character.

I just downloaded mixamo animation for my character player. In my Animator controller I added a new state and dragged in the animation.

Without the animation the player is standing fine. but with the animation the player is inside the ground.

# Answer
> 0 votes
In my case the solution is to check in enable true all the 3 Bake Into Pose. This did the trick

---
Tags: unity, c#
---