# Question
Title: How to monitor engagement via button clicks / purchases
I want to measure user engagement:

* Button clicks
* Purchases
* When they view a UI etc

I'd like to know at which point players enter the game and when they're most likely to stop playing.

What are some good ways to measure these things and generate graphs that make this information easy to visualise?

# Answer
> 0 votes
The short version is to grab a 3rd party library for handling analytics. There are a lot of great options out there, many of which are free. Which options you have depends on your platform (mobile, desktop, etc.) and your programming language (C++, C#, etc.).

The way to implement varies based on your library, but they are all roughly the same.

1. Import the library of your choice
2. Link it with their cloud solution
3. Add code to your project where you want the analytics to be called. For example, on a button press. The library's documentation will show you the specific code you need to add.
4. Go to the library's website and view your documention.

There are a lot of options to choose from, and it can be overwhelming. Some of the most reliable and affordable options are owned by major tech companies, so you may want to start there.

Examples include Firebase and PlayFab.

---

You can also write your own analytics tool, and link them to visualizers. This requires a lot more time and effort, and typically there is a dedicated person/team for writing this visualization.

Examples include Databricks + Tableau.

---

It is important to know what to analyze. You don't want to track too much, or it will be challenging to filter out important information. You don't want to track too little, or it won't have enough information. The best approach is to track too little, and then add information as you need it. Once you have data in your analytics, its probably there forever.

---

*Disclaimer: This is very much not my forte. Any data scientists out there...your answer would be much appreciated.*

---
Tags: marketing, statistics, telemetry
---


# Question
Title: How to add a texture that follows the movement?
I would like to move my landscape to simulate a world moving on the x-axis. I use `createPattern()` to add an image inside my path, but the pattern draws the image at the same position when the path is moving: the top of the "mountains" (the lines) move to the left, but the image stays where it is below the lines.

I generate some coordinates in an array, I draw a line between them and I add an offset with a setInterval. After each iteration, the position of each point is modified by the offset :

```
let path = 'M'+(points[i-1].x - offsetX)+' '+points[i-1].y;
path += 'L'+(points[i].x - offsetX)+' '+points[i].y;
//etc.

```

How could I add a texture that follows the movement?

You can see that the pattern is repeated even though the mountains have moved to the left :

edit :

The code :

```
function draw(){
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.translate(-moveX, 0);
  for (let i=Math.max(fromKeyPoint, 1); i<toKeyPoint; ++i){
    ctx.beginPath();

    ctx.lineCap = 'round';
    ctx.lineWidth = size;
    ctx.strokeStyle = color;
    ctx.moveTo(points[i-1].x, points[i-1].y);

    ctx.lineTo(points[i].x, points[i].y);
    ctx.stroke();

    let path = 'M'+(points[i-1].x)+' '+points[i-1].y;
    path += 'L'+(points[i].x)+' '+points[i].y;
    path += 'L'+(points[i].x)+' '+canvas.height;
    path += 'L'+(points[i-1].x)+' '+canvas.height;
    path += 'Z';
    let p = new Path2D(path);
    console.log("path : "+path);

    ctx.fillStyle = ctx.createPattern(imgTexture, "repeat");
    ctx.fill(p);
  }

```

# Answer
> 0 votes
Solution: so I had to clear the canvas when the context moves the canvas area.

```
ctx.clearRect(points[fromKeyPoint].x, 0, points[toKeyPoint].x, canvas.height);

```

and use `ctx.translate(-moveX, 0);` to move the mountains.

---
Tags: html-canvas, webgl
---


# Question
Title: Why would a bigger game move the gameworld around the Player instead of just moving a player within a gameworld?
So, this might be a little random since I can't remember any specific examples but this question just popped into my head 30mins ago and wont leave me alone. I remember hearing about some big game with decently sized gameworld that would move everything around a Player instead of moving the Player around. Note that this wasn't an endless runner or some other title of this kind that just tries to create an illusion of movement. Again, sorry but I'm not able to provide an example.

Either way, what are some advantages of treating movement like this for a game where it might result in moving more gameobjects at the same time than if only the Player would be moved?

# Answer
> 8 votes
For me, the prime example of this is Outer Wilds. However, it applies to other similar games. In the game, the player explores a solar system. This has the following implications:

* We have a huge space to explore.
* There are planets are moving all the time anyway.

Since everything is moving anyway, then moving everything instead of moving the player character is not really an extra cost.

---

And why would you want to move everything instead of moving the player character? Because floating point precision.

For a good example of the problems that floating point precision brings, let us see a game with huge worlds that does not do this: Minecraft. *See THE TRUE END of the MINECRAFT WORLD!.*

As you move away form the origin you will start to see problems.

This is because floating point numbers can represent more values near zero than away from zero.

In case you are not familiar with how floating point numbers work, first of all, here are a couple videos: Why Computers are Bad at Algebra | Infinite Series and Floating Point Numbers - Computerphile.

However, for the purposes of this answer, you can think of them as a scientific notation (with a mantissa and an exponent), or you can think of it as moving the decimal point (hence the name). These are the same idea: As the exponent becomes larger, you are moving the decimal point to the right, so that there are less digits after it.

Thus, the first symptom is that motion becomes jittery. This is because the difference between a floating point number value and the next becomes large enough that it is noticeable. Thanks to rounding, motion is still posible, but not smooth.

Eventually there there are no digits after the decimal point. And then you keep moving the decimal point (i.e. increasing the exponent), and the floating point numbers begin to skip integers altogether. When you reach those values we have another interesting behavior: a floating number value plus one is the same floating number value. Because the next integer cannot be represented as a floating point number, and is rounded down.

I remind you that the gap between values that can be represented becomes larger and larger. So for any gap you can think of, there will be a position where the gap between values that can be represented is larger… Well, eventually you reach the larger number that can be represented, and that is that.

What I'm going with this is this: eventually the distance that the player character would move is too small to make the gap between values that can be represented, and then the character can't keep moving.

And, of course, for any other system that depends on the position in your game (e.g. motion, models, lighting and shadows, world generation, etc) the progressive lose of precision as you move away from the origin will introduce weirder and weirder behavior.

To avoid all that you want to keep the player character near the origin. And that would mean to move the world.

---
Tags: movement
---


# Question
Title: How to destroy bullet on collision but only after it makes the collided object to bounce?
I made a scenario that shooting a bullets on crates make them both bounce nicely (both the bullet and crates are RigidBody2D & Colliders). When I use OnCollisionEnter2D to destroy the bullet when it hits the crate then the bullet destroyed before it pass the force to the crate and thus the crate stay still and not move physically...

How to make the crate move because of the bullet hit and also make the bullet to destroyed? There is more elegant way from just destroy the bullet a frame after the hit?

# Answer
An easy workaround is to disable SpriteRenderer component In OnCollisionEnter2D and you can then destroy bullet let say after half or a second. Something like,

```
void OnCollisionEnter2D(Collision2D other)
{
    // Assuming that your crate has tag of "crate"
    if (other.gameObject.tag == "crate")
    {
        GetComponent<SpriteRenderer>().enabled = false;
        Destroy(gameObject, 0.5f);
    }
}

```
> 1 votes

# Answer
Here are two similar strategies with tiny differences. I suggest the second approach.

The physics will happen the next FixedUpdate. So wait until that FixedUpdate is over. We can do this by waiting for FixedUpdate twice. The first pass will take us to when the physics start taking place. The second pass will take us to the FixedUpdate after the physics have completed.

```
void OnCollisionEnter2D(Collision2D other)
{
    StartCoroutine(DestroyAfterPhysics());
}

private IEnumerator DestroyAfterPhysics()
{
    yield return new WaitForFixedUpdate();
    yield return new WaitForFixedUpdate();
    Destroy(gameObject);
}

```

That code makes the assumption that all current physics will be dealt with during the immediate FixedUpdate. We can avoid this assumption and clean the code a bit by waiting for the maximum delta time. This version of the code will assure success, but possibly at the loss of an insignificant amount of time:

```
void OnCollisionEnter2D(Collision2D other)
{
    Destroy(gameObject, Time.maximumDeltaTime));
}

```

This is not a flawless approach, and I would be interested to see other ideas. For example, if you check to see if the bullet exists the frame after the collision, it could return a false positive.
> 1 votes

# Answer
This was the first result when I was trying to figure it out myself, so I wanted to post my solution after I got it working.

Not sure of the consequences of this just yet though.

In my case, I wanted a bullet impact to destroy the bullet after the collision made the receiving rigid body react to the collision.

Instead of:

```
void OnCollisionEnter(Collision collision)
    {
        AttemptToDamage(collision);
        Destroy(gameObject);
    }

```

Try

```
void OnCollisionEnter(Collision collision)
    {
        AttemptToDamage(collision);
    }
void OnCollisionStay(Collision collision)
    {
        Destroy(gameObject);
    }

```

I could be getting this wrong so someone please correct me if I'm mistaken, but my take of it is sort of like OnEnable vs Update, where OnCollisionEnter fires before the rest of the physics step, whereas OnCollisionStay fires after.

Either that or because my bullet is still colliding into the next physics step, OnCollisionStay fires anyway.

In both cases though, it does seem like the bullet both interacts with rigidbody and then subsequently is destroyed.

Hopefully this helps... 6 years later.
> 0 votes

---
Tags: collision-detection, unity, rigid-body-dynamics
---


title: Broken back face culling

text:
# Question
Title: Broken back face culling
I have an issue with back face culling in my engine on the monkey model from Blender exported as `.obj` format. However, with the box model from Blender exported the same way all is good.

My first assumption is that something's wrong with the winding order of certain faces in the monkey model. So I've tried to check order by calculating normals on each face by myself using the cross product `cross(v2-v1,v3-v1)`.

I expected that all normals would have Z-coordinate with the same sign, but got different results on different faces.

But why is the box, which I exported the same way, rendered correctly? So, I tried to calculate normals the same way on the box model–and wow!–I still get different Z signs on two faces out of twelve...

But I see that the box is rendered correctly, then I checked my method to calculate the faces' normals. And they calculated correctly–you can see them in the box GIF.

So the question is: did I correctly understood winding order? A I use the correct way to check the winding? Should all faces in the model have the same sign of Z for normals? Should I do additional geometry preparation for object models to render them all correctly?

* The engine follows the left-handed rule.
* Render API: Metal.
* All draws happen with backface culling and in clockwise order.

P.S.: online renderers of `.obj` models renders my monkey model correctly. I don't understand what to fix in my engine, cause my assumptions that normals should all have the same Z sign seems to be wrong.

Box:

```
<iframe src="https://giphy.com/embed/8Rtq2jXCowwkCIkFoK" width="480" height="400" frameBorder="0" class="giphy-embed" allowFullScreen></iframe><p><a href="https://giphy.com/gifs/8Rtq2jXCowwkCIkFoK">via GIPHY</a></p>
```

Monkey:

```
<iframe src="https://giphy.com/embed/Hvbi2wmktmfziLavii" width="480" height="400" frameBorder="0" class="giphy-embed" allowFullScreen></iframe><p><a href="https://giphy.com/gifs/Hvbi2wmktmfziLavii">via GIPHY</a></p>
```

# Answer
> 1 votes
After rotating that monkey a thousand times I noticed, that it actually hides back face triangles! Back face culling actually works fine. It's all about hiding polygons that covered by another polygons in front (depth test).

I didn't know that in Metal depth test is disabled by default. So after setup a depth buffer and adding a depth state to pipeline all works great.

Don't forget to check a depth test in those kind of cases =)

---
Tags: rendering, normals, culling
---


# Question
Title: Unity Shader w Color Bar for Fragment Color Manipulation
**Situation**

I have a shader for images with "wonky" colors - the reason the colors are so messy is because it's a sneaky way to encode data into the RGB color channels eg the red channel is terrain data the blue channel is water data and the green channel is lighting data (highlights & shadows).

I have color bars for each set of data eg I take the value for the red channel and find it's position on the color bar and that is the proper color to return for the pixel.

*Red Channel Data from original image*

*Color bar for Red Channel Data*

So that this point, as I'm looking at every pixel via my fragment shader, red values of `1` will pull from the color bar to the furthest right side (lighter colors) while values of `0` will pull from the color bar on the furthest left side (darker colors).

I have a basic fragment shader setup where I can get the respective color values from the image (main texture) and can read out the rgb values of each frag. I also have my color bar pulled into the shader via `sampler2D` but I'm not sure how to sample a color from the color bar based only the red value from the main tex's red value.

**Question**

Knowing the 0-1 value of red at every pixel on my mian texture, how can I return the associated color from the color bar?

*extra*

basics of my shader

```
Properties{
    _ColorBar("Color Bar", 2D) = "" {}
}

SubShader{
    // Cull off // for doublesized texture @jkr todo: disable for prod
    Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    ZWrite Off
    // ZTest Off
    Blend SrcAlpha OneMinusSrcAlpha
    // Cull front
    // LOD 100

    Pass {
        HLSLPROGRAM

        #pragma vertex vert
        #pragma fragment frag

        #include "UnityCG.cginc"

        ...

        sampler2D _MainTex; // maintex is set programatically at runtime
        sampler2D _ColorBar; // set via the unity inspector

        float4 frag(v2f f) : COLOR
        {
            fixed4 col = tex2D(_MainTex, f.uv);
            return col;
        }
        ENDHLSL
    }
}
FallBack "VertexLit"

```

Inspector View

# Answer
> 3 votes
To sample `_ColorBar` based on the 0-1 value of the `_MainTex`'s red channel, you can just use the sampled value's red channel as UV input to the `tex2D` function for the `_ColorBar`, like this:

```
fixed4 frag (v2f i) : SV_Target
{
     // sample the _MainTex at the uvs
     fixed4 color_from_map = tex2D(_MainTex, i.uv);

     // Sample the _ColorBar at the 0-1 red channel value of the color_from_map
     fixed4 sampled_color = tex2D(_ColorBar, color_from_map.r);
     return sampled_color;
}

```

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


# Question
Title: My character runs around on their own after picking up an object
I have a weird bug on my hands.

I am trying to create an event whereby the character walks into an object and automatically picks it up once the collision occurs.

The character can pick up the object (when the overlap begins it is attached to a socket on the character)

But immediately after this happens, the character runs around on their own without any input from me.

When the bug occurs, the character moves backward, facing and circling the point where the collision occurred. It's quite bizarre.

I created a project from the top-down template, then added the actor to be picked up and created the actual Blueprint. It is the only blueprint I've created.

Any ideas as to what could be happening here?

# Answer
The solution was to disable the object collision once the object had been picked up. Set the object collision to ignore the pawn channel like so.
> 0 votes

---
Tags: collision-detection, unreal-4, blueprints
---


# Question
Title: What is the typical way of authoring and implementing dynamic asset loading via blocks, in Unity?
Suppose that you have thousands of individual resources that need to be loaded dynamically (e.g. some kind of procedural or randomized world that spawns all manner of things etc). There are many ways you could manage the resource loading, like Resources, or AssetBundles, or Addressables, etc.

There is another option, which involves putting your asset data together into "block" files. This is done notably in Genshin Impact, if you look at their StreamingAssets folder. I would like to learn more about how this is typically implemented in the context of Unity, but cannot find many resources online about it.

Off the top of my head, this could be as simple as having an index table file to locate individual assets and then use file streams on the blocks to `Seek()` as needed and then load the bytes to build the assets, but I feel there may be more to it than just that: for example, there is specific folder structure separating the `.blk` files (folders going `00`, `01`, `02` etc instead of just putting all the blocks together and whatnot).

What is the typical way of authoring and implementing dynamic assets via blocks, in Unity? Are there guides/resources about this approach?

# Answer
The currently (2022) recommended way of doing this would be Addressable Assets.

The addressables system allows to organize assets in asset bundles by assigning them to "Groups". Asset bundles are archive files containing multiple assets. In order to optimize loading times, you usually should try to group each asset together with its dependencies (like a 3d model together with its textures) and also group assets together which are frequently loaded together (like all environment dodads which occur in the same biome). More about finding an ideal organisation strategy for your asset bundles can be found in the documentation section Organizing Addressable Assets.

However, there might still be some specialized cases where it can indeed make sense to build your own system. For example, when you have a very large open world map with long viewing distances which does not use the Unity terrain system and thus needs to be constructed and destroyed at runtime in various levels of detail as the player explores it (like in *Genshin Impact*, for example). In that case it can be useful to invent your own file format for storing map chunks. But as I said, you are dealing with a very special use-case here, which requires a very special solution tailor-made for the specific requirements of your game.

For example, you could have a solution which stores different levels of detail of each block in separate files. Or one where each block starts with the lowest-detail data and then continues with higher and higher detail versions. So the file parser can just stop reading as soon as it reached the desired level of detail. This could be accomplished pretty elegantly by storing the world geometry data in a spatial tree and serializing it in a breadth-first manner. But that's just one option of many. Again, there is no one-size-fits-all standard solution here. Your solution would be driven by how your custom terrain system works and by your specific requirements.
> 1 votes

---
Tags: unity, assets, resource-management
---


# Question
Title: How does a game client (offline) authenticate license from a license server (like Steam)?
So this question is pretty straightforward, but I honestly can't wrap my head around it. How does a client authenticate license from the license provider? For example, when you play a game which hosted on Steam, you will need to login to your account first, then when you run the game, it will check if whether you own the game then it will send you a license.

I understand until this part, but where does the authentication level happen? Is it in the Web API server or is it the local client? If it is on the Web Server, then what did the server send to acknowledge the authenticity and run the game? If it is on the local client, how does the the license pair created (how does the client validator assigned)?

I am thanking in advance for any hint or help.

**Edit**

To clarify the context of my question, I am building a prototype platform for hosting game(software) and act as a license server. However I am stuck at the authentication method and flow, thus why I use Steam as a reference point based on observation.

I only want to know what is the concept for software licensing especially in client-server relationship.

# Answer
First of all, a bullet-proof digital restriction management (DRM) system which reliably stops a user from executing a program which is already on their computer is impossible. You can put barriers in the users path to make it harder for them, but any such barrier can be overcome by a determined user. So forget about creating a solution which is completely impervious to *any* conceivable attack. All you can do is a solution which is difficult enough to overcome that the average user won't bother.

In the case of Steam, you don't run the game, you ask Steam to run the game. If you look at the properties of any of the shortcuts for Steam games on your desktop, you will notice that they are not actually pointing at the game executable. They are links in the form `steam://rungameid/1234567890` . What happens when you double-click on one of these shortcuts (or start the game from the Steam client) is

1. Steam is launched in the background (if it isn't already running).
2. Steam asks the user to authenticate with username and password (if they are not already logged in).
3. Steam contacts the Valve server to confirm that this user has a valid license for this game (*some* games allow offline play, but they still demand that the last license validation wasn't too long ago).
4. When the server confirms that the user has a valid license, then and only then does Steam launch the game executable.

Now it would of course still be possible for a technically versed user to locate the game executable in their Steam files and run it directly. In order to prevent this, the game executable might also try to confirm that the user owns the game on Steam on its own. But that's something the game developers would have to implement. For example, by using the Steamworks API in their game (When the user does not own the game on Steam, then even initializing the Steam API will fail). Note that the Steamworks API is not a stand-alone library. It requires a running instance of the Steam client with the user being logged in. Most of the functionality of the library will just contact the Steam client and asks it to fulfill the request. The Steam client might then delegate that request further to the Valve servers.

So the whole Steam DRM scheme hinges on one crucial component: The Steam client. If someone would hack their copy of the Steam client to bypass the license verification, then they could play games they downloaded through Steam and then refunded or copied from another Steam user.

It would also be possible to hack the game executable itself to no longer confirm the license by dummying out any Steamworks API calls. Now it would be possible to create a copy of it and run it without Steam.
> 1 votes

# Answer
I don't have the answer to how it is implemented by the systems, but I can imagine the mechanism could be based on public and private keys principles. It can be used in two ways; one is to make sure you can trust the sender and the other is to make sure the retriever is the one to be able to decode it.

If a person logs in on the server, the server knows what items that person has purchased. Since a game-PC is registered at the service, a combination of game and PC fingerprints could be used in a licence.

The combination of public and private keys means the server can send a message where the game knows it can only come from the server (because the message can only be decoded with the server's public key) and the game-PC can be identified because the server can decode the message that is encoded with the game-PCs public key. It could be a combination of messages back and forth that complete a validation handshake.
> 0 votes

---
Tags: client-server, licensing, authentication
---


# Question
Title: RuntimeInitializeOnLoadMethod only on certain scenes
I'm using `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]` to initialize a prefab that contains all the components required for the game to work propertly.

```
public class FrameworkInitializer : MonoBehaviour
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    public static void InitializeFramework()
    {
       Instantiate(Resources.Load("_GameEngine")) as GameObject;
    }
}

```

It works fine.

Now I'm creating some scenes to try out things before implementing them in the final game, and I don't really need the default prefab to initialize. I tried adapting the script to this:

```
public class FrameworkInitializer : MonoBehaviour
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    public static void InitializeFramework()
    {
        if (GameObject.FindWithTag("Framework Support") != null) return;
        if (GameObject.Find("NoFrameworkSupportRequired") != null)
        {
            Debug.LogWarning("Carla Framework initializer skipped because of NoFrameworkSupportRequired gameobject in scene.");
            return;
        }
        var framework = Instantiate(Resources.Load("_GameEngine")) as GameObject;
    }
}

```

But it's not working, because the scene is not loaded yet so it can't find any gameobject.

And if I change `BeforeSceneLoad` to `AfterSceneLoad`, some of the scripts that require the prefab in the `Awake` and `onEnable` cycle fails.

How can I make this script to run only on some of the scenes?

# Answer
> 0 votes
I think you might want to make your `_GameEngine`/framework the singleton.

```
public class Framework : MonoBehaviour {
    static Framework _instance;
    public static Framework Instance {
        get {
            if (_instance == null) {
                _instance = Instantiate(Resources.Load<Framework>("_GameEngine"));
            }
            return _instance;
        }
    }

    // On the _GameEngine prefab, assign references to each of the child components
    // that other scripts might want to look up.
    public DialogueSystemManager dialogue;
    public OtherManager other;
    // etc.
}

```

Now this behaves as a service locator. Anything else in your scene that wants to access a singleton manager does so via the `Framework`. ie..

```
DialogueSystemManager.Instance

```

becomes

```
Framework.Instance.dialogue

```

Now anytime anything references a manager contained in the `Framework`, it does so via the `Framework` singleton's lazy instantiation, ensuring it exists "just in time", but only when needed, so it won't get spawned in scenes where no one asks for it.

# Answer
> 0 votes
I had the same question when setting up some test scenes that I did not want to use my manager GameObject. I am using a similar method, also setting DontDestroyOnLoad after instantiation.

I ended up checking the scene name beforehand. The method using `RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)` does appear to know the name of the scene, even though it has not loaded yet.

Include in your namespaces:

```
using UnityEngine.SceneManagement;

```

And then do whatever check you want to do in the function before the instantiation. In my case, I am excluding any Scene that starts with "Test", along with the default scene name created by Unit Tests (e.g. "InitTestScene637801810867719397"):

```
Scene scene = SceneManager.GetActiveScene();
if (!scene.name.StartsWith("Test") && !scene.name.StartsWith("InitTestScene"))

```

---
Tags: unity
---


# Question
Title: Presenting difficulty settings without words?
I am trying to make a game without any text. I'm using icons in place of them to describe various aspects of the game (health, armor, stats) without using English language.

I am wondering if anyone has a good solution for preventing a difficulty selection as an icon. Increased difficulty in the game makes the QTEs more forgiving and player stats slightly stronger.

I can't think of a universally understandable way to present the choice between easy, medium, and hard difficulties.

# Answer
> 2 votes
One thing I would recommend is separating this difficulty setting into **two independent settings**. Players with motor, visual, or cognitive disabilities, or otherwise slow reaction times, might benefit from more forgiving QTEs, while still enjoying the strategic challenge and drama that comes from playing with lower character stats. Or vice versa, a player who's not strong in the game's strategy might want higher stats to compensate, while still liking QTE timings be tight enough to be challenging for them. By de-bundling the setting, each player can mix and match options to get the experience that's most comfortable and satisfying for them.

The separation can also help with communication. Each option becomes about one specific thing, so it's easier to convey. And by presenting the two settings side-by-side, the player can read cues from each to understand the suggested gradient between easier and harder options - so if one setting is vague on its own, the context from the adjacent setting can help guide interpretation.

You could also leverage colour language or emoji expressions to help sell this association.

Here I've used some CC BY 3.0 icons by Delapouite, Lorc, and Skoll, via Game-icons.net \- if I've chosen the icons, colours, and layout well, I I won't have to explain which one means what.

# Answer
> 0 votes
Skull icons in increasing amounts to reflect increasing difficulty.
For example:

```
|  |  |  |

```

---
Tags: ui-design, graphics-design
---


# Question
Title: How to correctly synchronize a shared surface?
I am trying to share a direct3d9 surface between two processes. One process (let's call it A) writes to the surface, and the other (B) displays it on screen. Currently, process A does a StretchRect of its rendering surface to a shared surface, and then sets a flag in shared system memory to tell B that it's done. When B sees the flag, it then does a StretchRect of the shared surface to its own display surface. Process B then sets the flag again to tell A it is done.

It seems however that after the StretchRect on the shared surface returns, the texture has not necessarily finished copying, because sometimes Process B gets the previous picture, or sometimes even there is tearing (i.e. one half of picture N + one half of picture N + 1).

As I understand it, Direct3D is largely asynchronous under the hood, and does not ensure synchronisation between processes. I therefore need to ensure by myself that Process A has finished copying before displaying in process B, and vice-versa. Am I correct in my interpretation of the situation, and how would I achieve this? I am experimenting with LockRect() but I'm not sure if that's optimal or even guaranteed to work.

From MSDN documentation:

> Shared cross-process surfaces provide no synchronization mechanism. Read/write changes to a shared surface may not reflect a referencing process's view of the surface when expected. To provide synchronization, use event queries or lock the texture.
>
> Only the process that initially creates a shared resource can lock it (any process that opens a reference to that shared resource cannot lock it).

# Answer
> 0 votes
your res sharing process is OK, I think. In dx9ex theres a flag in Present called D3DPRESENT\_FORCEIMMEDIATE, can be used to force GPU render the resource, and then use the right picture later.

---
Tags: c++, directx
---


# Question
Title: One sqlite db per savegame or one big sqlite db for all the savegames?
when you develop a simple local game, with 4 slots for history mode, wich option is better to persist the savegame of the history slot openned by the user?

The game has 4 entities with some simple relations between them. Which whould be the best option? A single db file with all stored inside, or one db for each savegame?

# Answer
Hi and welcome to GameDev. I haven't used SQLite in a couple of years (last time was when I also developed an android game), but I've been using MySQL on the back-end in all of my games for years and most of the principles apply to both.

My general advice would be to keep all saved games in one database and structure your database correctly (i.e. normalise it etc.). Part of my rationale here is if you are storing what would normally be stored in a "saved games" table like date\_saved etc., then writing queries against this table looking for most recent saves etc. will be much easier than having to do the same thing across different databases.

Hope this helps.
> 1 votes

---
Tags: android, databases, sql
---


# Question
Title: Why is button component's animation transition just working for some buttons?
I have a main menu scene in which the buttons work using button component's animation transition. I created a simple animation for them that changes their vertex color to blue when selected. The problem is that surprisingly, some of them don't work this way. In fact, they don't even work with other transitions such as color tint.

As you can see in the gif, the animation transitions are working fine. But the truth is that these are (plus a few other buttons in the options menu) the only buttons that have working transitions.

When you press the quit button, a small panel shows up that asks if you really want to quit the game. This is where the problem appears. Although the yes button should be selected based on the script, it just stays unselected which also shows that the transition animation is not working. I've checked these buttons using animation tab's preview mode and they seem to work fine there but when the actual game starts, they just remain unselected.

I realized that there should be a big structural difference between the buttons that work and those that don't but I'm not able to find it. To prove this, I changed the transition mode of new game button (that is working fine) and the highlighted and selected color turned blue but when I did the same for the yes button (which cannot be selected), there was no change in the colors.

This is the part in my main menu script that controls the exit panel. I don't see any problems in the script as I don't in the editor. But still, some of the buttons can't be selected when the condition is due (All the game objects are assigned in the inspector).

```
   public void OpenExitPanel()
    {
        exitPanel.SetActive(true);
        EventSystem.current.SetSelectedGameObject(null);
        EventSystem.current.SetSelectedGameObject(exitPanelFirstButton);
        mainMenu.SetActive(false);
    }

    public void CloseExitPanel()
    {
        exitPanel.SetActive(false);
        EventSystem.current.SetSelectedGameObject(null);
        EventSystem.current.SetSelectedGameObject(exitPanelClosedButton);
        mainMenu.SetActive(true);
    }

```

I also tried creating new buttons (Text Mesh Pro) but again, some of the transitions work and some don't.

This problem is also present in the pause menu but unlike the main menu, none of the buttons can be selected there. I even used Debug.Log to check and see if the first button is selected and it was; but still the animation transition doesn't work.

I believe that this is a Unity bug but I decided to ask it here just to see if I'm missing something.

Thank you in advance.

# Answer
> 0 votes
The solution was simple. I forgot to assign the function in the On Click() function in the inspector of the quit button. I mistakenly had assigned SetActive() function. Now it works.

PS: Be sure to use the code in the question. There is no need to use the coroutine for making this to work.

---
Tags: unity, c#, animation, unity-ui, animator
---


# Question
Title: Why can't I use the "degrees" character in HLSL comments?
I was in the process of creating a function in my compute shader that converts a 180° angle to a 360° CCW angle like this:

```
// Calculates the 360° angle counter-clock-wise
float angle360(in float2 a, in float2 b)
{
    float angle = angle180(a, b);
    // Right hand rule: When b is to the left of a, a x b points up -> take the "opposite" of the 180° angle in the 360° "space"
    if (cross(float3(a, 0), float3(b, 0)).z > 0)
        angle = 360 - angle;
    return angle;
}

```

But when I went back to the Unity Editor it complained to me that there was a "unrecognised identifier 'INVALID\_UTF8\_STRING' at kernel CSMain" on line 1

When I deleted the comments the error went away, and it doesn't happen with any other comment, only these, and they are also the only ones that contain the `°` character. So my question is, why doesn't the shader compiler (I assume) like that I use this character?

# Answer
The issue was with the encoding of the file, as it was not encoded in UTF8. Setting it to the UTF8 encoding in VS solved the issue.

If you want to know how to set the encoding in a file in VS, follow this tutorial here
> 3 votes

---
Tags: unity, hlsl, compute-shader
---


# Question
Title: Libgdx OrthogonalTiledMapRenderer doesn't render properly
I will simply leave a clip of it as it's easier than describing the problem. https://i.stack.imgur.com/bBAVC.jpg

This is All the code that i have

```
class MainScreen : Screen
{
    var map = Map(System.currentTimeMillis(), 32, 32, 24,24)
    lateinit var renderer : OrthogonalTiledMapRenderer
    /** Called when this screen becomes the current screen for a [Game].  */
    override fun show() {
        viewport = ExtendViewport(8f, 8f, 64f, 46f)
        rendererCamera = OrthographicCamera(viewport.worldWidth, viewport.worldHeight)

        renderer = OrthogonalTiledMapRenderer(map, 1/ viewport.minWorldWidth)

        Gdx.input.inputProcessor = InputMultiplexer(InputInheritor())
        viewport.camera.position.set(ceil(viewport.camera.position.x), ceil(viewport.camera.position.y), 0f)
    }

    /** Called when the screen should render itself.
     * @param delta The time in seconds since the last render.
     */
    override fun render(delta: Float) {
        ScreenUtils.clear(Color.DARK_GRAY)

        checkInput(this, delta)

        mainBatch.projectionMatrix = viewport.camera.combined
        viewport.apply()
        renderer.render()
        renderer.setView(viewport.camera as OrthographicCamera)

        viewport.camera.update(true)
        uiViewport.camera.update()
    }

```

and my tiled map generator class

```
class Map : TiledMap {
    lateinit var noise: OpenSimplexNoise
    var seed = 1

    lateinit var thisLayer : TiledMapTileLayer
    constructor() : super()
    constructor(seed:Long, width: Int, height: Int, tileWidth: Int, tileHeight: Int)
    {
        var layer = GenerateMap(seed, width, height, tileWidth, tileHeight)
        thisLayer = layer
        layers.add(thisLayer)
    }
    companion object {
        fun GenerateMap(seed: Long, width: Int, height: Int, tileWidth: Int, tileHeight: Int): TiledMapTileLayer
        {
            var toReturn = TiledMapTileLayer(width, height, tileWidth, tileHeight)
            var noise = OpenSimplexNoise(seed)
            for (x in 0 until toReturn.width)
                for (y in 0 until toReturn.height)
                {
                    var tile: StaticTiledMapTile
                    var eval = noise.eval(x.toDouble(), y.toDouble())
                    if (sin(eval) >0.15f) tile = StaticTiledMapTile(atlas.findRegion("tileGrass1"))
                    else tile = StaticTiledMapTile(atlas.findRegion("tileSand1"))
                    var cell = TiledMapTileLayer.Cell()
                    cell.tile = tile
                    toReturn.setCell(x, y, cell)
                }
            return toReturn
        }
    }

}

```

and my atlas cache wrapper:

```
class AtlasWrapper
{
    var cache = mutableMapOf<String, TextureAtlas.AtlasRegion>()
    lateinit var atlas: TextureAtlas
    constructor(directory: String)
    {
        atlas = TextureAtlas(directory)
    }
    constructor(atlasArg: TextureAtlas)
    {
        atlas = atlasArg
    }
    fun findRegion(region: String) : TextureAtlas.AtlasRegion
    {
        if(cache.containsKey(region)) return cache[region]!!
        val atlasRegion = atlas.findRegion(region)
        cache[region] = atlasRegion
        return atlasRegion
    }
}

```

the problem is at the `tile = Staticmaptile()` portion of the code as when i replace it with a normal TextureRegion nothing breaks. Any help would be appreciated

edit: those two tiles are identical in dimensions

# Answer
I've solved this problem, as i think, the culprit was that the texture was 128px wide/tall and i set it to 32 pixels in tileWidth of the map constructor, which i guess libGDX doesn't like, i fixed it by changing stuff to as such:

```
    var map = Map(System.currentTimeMillis(), 16, 16, 32,32)
to
    var map = Map(System.currentTimeMillis(), 16, 16, 128,128)

```

```
    renderer = OrthogonalTiledMapRenderer(map, 1/TILE_SIZE)
to
    renderer = OrthogonalTiledMapRenderer(map, 1/TILE_SIZE * TILE_SIZE/128f)

```

I first tried to simply set width to 128 but it didn't work so i thought id multiply the tile size by a factor of ratio of a normal tile's pixel size / its actual pixel size and everything now works and it (probably) isn't about textureRegions being broken
> 0 votes

---
Tags: java, libgdx, kotlin
---


title: Dash Cool Down Problem Unity2D

text:
# Question
Title: Dash Cool Down Problem Unity2D
I need help in adding a cooldown feature to my dash ability. I tried to look online for solutions, but when I add it into my script, the dash does not work anymore.

I would appreciate some help as I have been working on this for days.

Disclaimer: this is not my code, and I just found it on YouTube by MuddyWolf.

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

public class DashAbility : MonoBehaviour
{
    //dash variables
    public float dashDistance;
    bool isDashing;
    float doubleTapTime;
    KeyCode lastKeyCode;
    [SerializeField] Rigidbody2D rb;

    void Update()
    {
        //Dashing Left

        if (doubleTapTime > Time.time && lastKeyCode == KeyCode.A)
        {
            StartCoroutine(Dash(-1f));
        }
        else
        {
            doubleTapTime = Time.time + 0.3f;
        }

        //Dashing Right
        if (doubleTapTime > Time.time && lastKeyCode == KeyCode.D)
        {
            StartCoroutine(Dash(1f));
        }
        else
        {
            doubleTapTime = Time.time + 0.3f;
        }

    }

    IEnumerator Dash(float direction)
    {
        isDashing = true;
        rb.velocity = new Vector2(rb.velocity.x, 0f);
        rb.AddForce(new Vector2(dashDistance * direction, 0f), ForceMode2D.Impulse);
        float gravity = rb.gravityScale;
        rb.gravityScale = 1;
        yield return new WaitForSeconds(0.2f);
        isDashing = false;
        rb.gravityScale = gravity;
    }
}
```
</code></pre>

# Answer
> 3 votes
I say this only because this code is not yours: **this code is horrific**. I would not use any code from this source. Some of the problems:

* Comparing against / adding offsets to `Time.time`. Because this is a single-precision float storing the total number of seconds the game has been running, it grows in magnitude and loses precision over time. If you're making a game that can be suspended and resumed, it might accumulate more than 9 hours of continuous play across multiple sessions, and start showing millisecond-sized errors in your double-tap timings.
* Calling a variable a `distance` but using it as an `Impulse`. If your code advertises to the developer tuning it that putting a "5" here means it will dash 5 units, it should do the math to ensure that the dash goes exactly 5 units of world space distance. Not apply an impulse of 5 Newton-seconds. (Do you know how far an impulse of 5 Newton-seconds will push a character? I sure don't, and it's not the designer's job to do that conversion!)
* Using hard-coded key codes (`KeyCode.A`) instead of logical input actions (like "Dash Left"). This will make it harder if you ever want to port to a platform that does not use a keyboard (like gamepad controls or touch controls on mobile), or if you want to support input remapping options the player can choose. (Which I'd recommend, if you plan to sell your games commercially. Input remapping is important to player comfort and accessibility)
* Magic numbers that aren't set as named constants or exposed as tuning parameters. If you ever wanted to change the double-tap window for example, you'd have to change the `0.3` in multiple places. Missing one would give you inconsistent double-tap timings going in one direction versus the other, while doing a global find & replace might alter `0.3`s that had nothing to do with double-tap.

Be very careful copying code you don't understand from YouTube. Just because someone has a YouTube channel does not mean they're a good programmer, or that what they're showing you is a good way to do things.

---

So, how would we do this if we wanted to not just make something quick to throw up on YouTube, but actually build a game we could ship cross-platform down the line if we wanted to?

Rather than rolling your own code for timing a double-tap, let's use what Unity already has built into the new Input System package. This will be a bit of an adjustment at first, but it will make your life much easier if you need to support alternate control mappings in future, so it's worth learning how to use it.

Follow the setup instructions here to install and enable the Input System in your project. Note that this will break anything relying on the legacy Input Manager (`Input.GetButton`/`Key`/`Axis`...), so you may have a few bits of code to refactor, but better to do that early in a project when you don't have much code than at the end when changing anything is that much harder.

In your assets folder, right-click and select Create -\> Input Actions, and set up an Input Actions Asset something like this:

Note that I've made two logical actions for Dash Left and Dash Right. Each one is set up as a Button-type action, and listens to three bindings: keyboard arrow keys, WASD keys, and the D-Pad of a gamepad. Already the game is supporting multiple input types out of the box, with no extra code on our part. And, these are also easier to remap if you want to add that feature in future. Each of these bindings is configured to fire on "Multi-Tap" using the project default settings - so you have one place where you can tune every double-tap timing at once, uniformly.

You can add more input actions to the list, or even add alternative mappings for menus or different modes (like if your character can switch between forms or vehicles that need their own distinct controls).

We can add a script that works with the Input System like this (there are other methods too, but this is a convenient one):

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

[RequireComponent(typeof(Rigidbody2D))]
public class Dash : MonoBehaviour
{
    public float dashDuration = 0.2f;
    public float dashDistance = 1.0f;
    public float cooldownDuration = 1.0f;

    Coroutine _dashInProgress;

    // Auto-populate our Rigidbody reference.
    [SerializeField, HideInInspector]
    Rigidbody2D _rb;

    void OnValidate() {
        if (_rb == null) _rb = GetComponent<Rigidbody2D>();
    }

    public void OnDashLeft(InputAction.CallbackContext context) {
        if (context.performed) TryDash(-1);
    }
    public void OnDashRight(InputAction.CallbackContext context) {
        if (context.performed) TryDash(1);
    }

    ///
    /// Attempt to perform a dash move.
    ///
    /// <param name="direction">1 to dash right, -1 to dash left.</param>
    /// <returns>true if dash is performed, false if dash is on cooldown.</returns>
    public bool TryDash(int direction) {
        // Don't start a new dash if we're currently dashing, or on cooldown.
        if (_dashInProgress == null) return false;

        // Otherwise, start a new dash, and remember that it's in progress.
        _dashInProgress = StartCoroutine(PerformDash(direction));
        // Report success to whoever called this.
        return true;
    }

    IEnumerator PerformDash(int direction) {
        float targetVelocity = direction * dashDistance / dashDuration;

        // Because this was in your source script - unclear to me why you need
        // to change gravity scale, but I assume you have good reason.
        float cachedGravity = _rb.gravityScale;
        _rb.gravityScale = 1f;

        // Stop any fall or rise in progress and dash horizontally.
        _rb.velocity = new Vector2(targetVelocity, 0);

        // Every physics step, set our horizontal velocity to
        // achieve the target distance over the dash duration.
        for (float t = 0; t < dashDuration; t += Time.deltaTime) {
            yield return new WaitForFixedUpdate();
            // Allow the character to start to fall during a dash,
            // by preserving the y component of the velocity.
            var v = _rb.velocity;
            v.x = targetVelocity;
            _rb.velocity = v;
        }

        // Put gravity back the way we found it.
        _rb.gravityScale = cachedGravity;

        // Prevent a new dash from starting until we're past our cooldown.
        yield return new WaitForSeconds(cooldownDuration);

        // Clear out the dash in progress, so a new one can start.
        _dashInProgress = null;
    }
}

```

Now add a Player Input component to your character object, and set its Actions to use the Input Actions Asset and Gameplay mapping we just created.

Set its Behaviour to "Invoke Unity Events", and wire up the Dash Left / Dash Right gameplay actions to invoke our `DashLeft()`/`DashRight()` methods, respectively.

And there we have it. Dash on double-tap, without having to manage button mappings and press intervals in our own code. This style is much more robust to future changes than the YouTube example, and as a bonus, its `distance` variable actually measures a distance in worldspace units!

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


# Question
Title: Can't install Unity after Hub froze during installation - where to find Unity files and delete them?
I'm struggling to reinstall Unity after Hub crashed halfway through installing an editor version.

I have tried to delete the partially installed Unity - but I don't know all the locations to look, as any new attempts to load Unity are blocked by older files.

There is no Unity running. I checked in Task Manager. I had made sure the directory was empty before I reinstalled. I also restarted the Hub before I started the new installation (just in case) then removed Hub, and after that all Unity versions....

Running Windows 10.

# Answer
> 1 votes
Press the Locate button on the Installs tab of the hub.

That will bring up a folder showing the install path of the editors.

# Answer
> 1 votes
The problem was caused by folder permissions, which needed to be changed on the `.bin` file. The old file couldn't be overwritten. Here is the console output I was getting during an installation attempt:

```
CommandWithNoStdoutInvokationFailure: Gradle initialization failed.
The option setting android.enableR8=false' is deprecated.
WARNING: The option setting 'android.enableR8=false' is deprecated.
PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
C:\Users\bb\.gradle\caches\6.1.1\file-changes\last-build.bin (Access is denied)

```

Unchecking the read-only permissions checkbox on last-build.bin fixed all the other problems, and my game is running now on Android.

---
Tags: unity, windows
---


# Question
Title: Rendering Unreal Engine 4 sequence: character timeline animations don't show, and behave as if they are in play mode
I have a cinematic sequence with camera cuts set up that can be previewed properly. These scenes involve human skeletal character animations that I made frame by frame in the timeline. Everything works fine in the timeline preview, but when I start to render out the cinematic, the human characters function as if they are in "play" mode, namely dropping down to the ground directly, without playing out the animations that I made. Why is this? How could I fix it?

# Answer
In the sequence timeline, make sure the `SkeletalMeshComponent0` exists besides the `ControlRig`.

Click on the characters. In the Details panel, uncheck the "Enable Gravity" option.

Then it's fixed!
> 0 votes

---
Tags: animation, rendering, unreal-4, skeletal-animation, video
---


title: Multiple Lines with Single LineRenderer

text:
# Question
Title: Multiple Lines with Single LineRenderer
I have a database of country, state, and even county level borders and I'm stuck in a situation where I either have 1000+ linerenderers in the scene OR I have a single line that connects every border across the globe, neither of which is desirable.

Part of the issue is how the data comes in, in tiny chunks of 4-5 points that may be in the us then the next set of points will be in china. It seems there's no "simple" way to do this so I'm starting to think I'll need to do all my draws with a shader OR draw lines to a material.

Is there any way to use a single `LineRenderer` that has sizable gaps in the line?

\** EDIT \**

Playing around with some things and I've condensed all the line draw to per map tile and performance is already WAY up. The problem now is that I have lines stretching across the map in multiple places since I haven't found a good way to put an "invisible" line section in the middle of a line renderer series

# Answer
There's "the right way" to solve this issue and then there's the sneaky way. I took the sneaky way:

For the "move to" line operations I'm doing the following:

* add a point to the linerenderer that goes BEHIND my material (so it's not visible)
* while behind the material I then draw a line to the where the new drawing location will be
* I draw an third line back to the surface of the material
* continue "line to" instructions
> 1 votes

---
Tags: unity, lines, line-renderer
---


# Question
Title: Make types, levels, armor and weapons for an text based adventure game, java
So i plan on doing a text based adventure game in java. And right now iam planning my game. I came up with different types of player (exp. attacker, defender. etc) weapons, potions (health potions, damaging potions etc) and armor.

Since I am fairly new to Java I clueless right now. The only thing that comes to my mind is a big if statement but I think that's not a smart solution, and there must be a different way to solve this.

I can't provide any code right now because I didn't start to code but what I would like to know is: How to make and save player infos like levels and items for the next attack without doing a lot of if statements. You can also give me some keywords and I will research it that's no problem!

# Answer
Java is an object-oriented language, so the usual approach to this would be a class hierarchy.

Create a class for each of the entity types mentioned in the question. Then represent those entities at runtime with instances of those classes.

Objects which have the same functionality but have different numbers should be instances of the same class which differ by their data:

```
HealthPotion smallHealthPotion = new HealthPotion(20);
HealthPotion mediumHealthPotion = new HealthPotion(50);
HealthPotion largeHealthPotion = new HealthPotion(250);

```

Objects which share most of their logic but also have some different game mechanics should be represented by classes inheriting from the same base class. For example, healing potions and damaging potions might inherit from the same base class `Potion`. `Potion` would implement the functionality and carry the data you have in all potions, while the classes `HealthPotion` and `DamagePotion` would have the logic and data specific to the more specialized potion types.

```
Potion smallHealthPotion = new HealthPotion(20);
Potion smallPoisonBottle = new DamagePotion(20);

```

The nice thing about class inheritance is that you can have code like this:

```
Potion potion = GetPotionFromInventorySlot(31);
potion.drink(selectedPlayer);

```

The method `drink(PlayerCharacter drinker)` would be declared in `Potion` but implemented in both `HealthPotion` and `DamagePotion` in different ways (one doing good stuff to the drinker, the other bad stuff). Depending on what type of potion is in inventory slot 31, the Java runtime environment would either run the method `HealthPotion.drink` or `DamagePotion.drink`. No `if(typeof(potion) == ...)` required. This is called polymorphism.

---

Caveats:

* The above code samples are grossly oversimplified. Real-world code would pass a lot more data to those constructors than just a single number, or would use a creational pattern like a Factory or Builder.
* If you want to take this project serious, then you might also want to consider reading item names and stats from a configuration file instead of hardcoding them.
* There is no "right" or "wrong" way to design your games software architecture. Just ways which work for you or ways which don't work for you.
> 1 votes

---
Tags: java, levels, text-based
---


title: Replace Volumetric Clouds With Mesh?

text:
# Question
Title: Replace Volumetric Clouds With Mesh?
I'm looking to replace the Volumetric Cloud shader, or at least edit it in some way, to replace the clouds with a mesh. I'd like the meshes to be duplicated (without duplicating into one another,) and randomly rotated. If anyone knows how I can possibly create this effect, please let me know. Thank you! :)

# Answer
> 0 votes
Have you looked into Marching Cubes? You can run it as a geometry shader. It converts a scalar field (fog density) into a mesh by generating an isosurface.

I have a C++ CPU implementation of Marching Cubes here: https://github.com/sjhalayka/marching\_cubes

If you need GPU code, here is the sample geometry shader, in OpenGL 4 anyway:

```
#version 430 core

layout (points) in;
layout (triangle_strip) out;
layout (max_vertices = 15) out;

in VS_OUT
{
    vec4 position0;
    vec4 position1;
    vec4 position2;
    vec4 position3;
    vec4 position4;
    vec4 position5;
    vec4 position6;
    vec4 position7;
    float threshold;
} gs_in[];

struct grid_cube
{
    vec4 vertex_val[8];
};

    const int MC_EdgeTable[256]={
    0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
    0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
    0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
    0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
    0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
    0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
    0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
    0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
    0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
    0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
    0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
    0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
    0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
    0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
    0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
    0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, // mirrors here...
    0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
    0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
    0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
    0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
    0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
    0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
    0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
    0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
    0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
    0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
    0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
    0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
    0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
    0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
    0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
    0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0   };

 const int MC_TriTable[256][16] =
    {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
    {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
    {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
    {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
    {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
    {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
    {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
    {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
    {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
    {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
    {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
    {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
    {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
    {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
    {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
    {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
    {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
    {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
    {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
    {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
    {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
    {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
    {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
    {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
    {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
    {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
    {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
    {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
    {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
    {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
    {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
    {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
    {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
    {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
    {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
    {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
    {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
    {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
    {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
    {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
    {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
    {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
    {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
    {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
    {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
    {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
    {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
    {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
    {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
    {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
    {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
    {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
    {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
    {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
    {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
    {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
    {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
    {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
    {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
    {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
    {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
    {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
    {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
    {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
    {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
    {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
    {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
    {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
    {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
    {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
    {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
    {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
    {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
    {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
    {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
    {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
    {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
    {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
    {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
    {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
    {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
    {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
    {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
    {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
    {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
    {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
    {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
    {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
    {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
    {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
    {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
    {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
    {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
    {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
    {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
    {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
    {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
    {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
    {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
    {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
    {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
    {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
    {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
    {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
    {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
    {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
    {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
    {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
    {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
    {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
    {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
    {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
    {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
    {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
    {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
    {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
    {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
    {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
    {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
    {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
    {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
    {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
    {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
    {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
    {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
    {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
    {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
    {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
    {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
    {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
    {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
    {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
    {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
    {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
    {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
    {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
    {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
    {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
    {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
    {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
    {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
    {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
    {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
    {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
    {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
    {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
    {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
    {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
    {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
    {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
    {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
    {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
    {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
    {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
    {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
    {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
    {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
    {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
    {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
    {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
    {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
    {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
    {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
    {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
    {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
    {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
    {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
    {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
    {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
    {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
    {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
    {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
    {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
    {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
    {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
    {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
    {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
    {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
    {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
    {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};

int lessthan(vec4 left, vec4 right)
{
    if(left.x < right.x)
        return 1;
    else if(left.x > right.x)
        return 0;

    if(left.y < right.y)
        return 1;
    else if(left.y > right.y)
        return 0;

    if(left.z < right.z)
        return 1;
    else if(left.z > right.z)
        return 0;

    return 0;
}

vec4 vertex_interp(vec4 v0, vec4 v1)
{
    if(0 == lessthan(v0, v1))
    {
        vec4 temp = v0;
        v0 = v1;
        v1 = temp;
    }

    const float epsilon = 1e-10f;

    if(abs(gs_in[0].threshold - v0.w) < epsilon)
        return(v0);

    if(abs(gs_in[0].threshold - v1.w) < epsilon)
        return(v1);

    if(abs(v0.w - v1.w) < epsilon)
        return(v0);

    float mu = (gs_in[0].threshold - v0.w) / (v1.w - v0.w);

    return v0 + (v1 - v0)*mu;
}

int tesselate_grid_cube(grid_cube grid)
{
    int cubeindex = 0;

    if(grid.vertex_val[0].w < gs_in[0].threshold) cubeindex |= 1;
    if(grid.vertex_val[1].w < gs_in[0].threshold) cubeindex |= 2;
    if(grid.vertex_val[2].w < gs_in[0].threshold) cubeindex |= 4;
    if(grid.vertex_val[3].w < gs_in[0].threshold) cubeindex |= 8;
    if(grid.vertex_val[4].w < gs_in[0].threshold) cubeindex |= 16;
    if(grid.vertex_val[5].w < gs_in[0].threshold) cubeindex |= 32;
    if(grid.vertex_val[6].w < gs_in[0].threshold) cubeindex |= 64;
    if(grid.vertex_val[7].w < gs_in[0].threshold) cubeindex |= 128;

    if(0 == MC_EdgeTable[cubeindex])
        return 0;

    vec4 vertlist[12];

    if(MC_EdgeTable[cubeindex] & 1)
        vertlist[0] = vertex_interp(grid.vertex_val[0], grid.vertex_val[1]);

    if(MC_EdgeTable[cubeindex] & 2)
        vertlist[1] = vertex_interp(grid.vertex_val[1], grid.vertex_val[2]);

    if(MC_EdgeTable[cubeindex] & 4)
        vertlist[2] = vertex_interp(grid.vertex_val[2], grid.vertex_val[3]);

    if(MC_EdgeTable[cubeindex] & 8)
        vertlist[3] = vertex_interp(grid.vertex_val[3], grid.vertex_val[0]);

    if(MC_EdgeTable[cubeindex] & 16)
        vertlist[4] = vertex_interp(grid.vertex_val[4], grid.vertex_val[5]);

    if(MC_EdgeTable[cubeindex] & 32)
        vertlist[5] = vertex_interp(grid.vertex_val[5], grid.vertex_val[6]);

    if(MC_EdgeTable[cubeindex] & 64)
        vertlist[6] = vertex_interp(grid.vertex_val[6], grid.vertex_val[7]);

    if(MC_EdgeTable[cubeindex] & 128)
        vertlist[7] = vertex_interp(grid.vertex_val[7], grid.vertex_val[4]);

    if(MC_EdgeTable[cubeindex] & 256)
        vertlist[8] = vertex_interp(grid.vertex_val[0], grid.vertex_val[4]);

    if(MC_EdgeTable[cubeindex] & 512)
        vertlist[9] = vertex_interp(grid.vertex_val[1], grid.vertex_val[5]);

    if(MC_EdgeTable[cubeindex] & 1024)
        vertlist[10] = vertex_interp(grid.vertex_val[2], grid.vertex_val[6]);

    if(MC_EdgeTable[cubeindex] & 2048)
        vertlist[11] = vertex_interp(grid.vertex_val[3], grid.vertex_val[7]);

    int ntriang = 0; // Max triangles == 5

    for(int i = 0; MC_TriTable[cubeindex][i] != -1; i += 3)
    {
        vec4 vertex0, vertex1, vertex2;

        vertex0.x = vertlist[MC_TriTable[cubeindex][i]].x;
        vertex0.y = vertlist[MC_TriTable[cubeindex][i]].y;
        vertex0.z = vertlist[MC_TriTable[cubeindex][i]].z;
        vertex0.w = 0;

        vertex1.x = vertlist[MC_TriTable[cubeindex][i + 1]].x;
        vertex1.y = vertlist[MC_TriTable[cubeindex][i + 1]].y;
        vertex1.z = vertlist[MC_TriTable[cubeindex][i + 1]].z;
        vertex1.w = 0;

        vertex2.x = vertlist[MC_TriTable[cubeindex][i + 2]].x;
        vertex2.y = vertlist[MC_TriTable[cubeindex][i + 2]].y;
        vertex2.z = vertlist[MC_TriTable[cubeindex][i + 2]].z;
        vertex2.w = 0;

        gl_Position = vertex0;
        EmitVertex();
        gl_Position = vertex1;
        EmitVertex();
        gl_Position = vertex2;
        EmitVertex();

        EndPrimitive();

        ntriang++;
    }

    return ntriang;
}

void main(void)
{
    grid_cube g;
    g.vertex_val[0] = gs_in[0].position0;
    g.vertex_val[1] = gs_in[0].position1;
    g.vertex_val[2] = gs_in[0].position2;
    g.vertex_val[3] = gs_in[0].position3;
    g.vertex_val[4] = gs_in[0].position4;
    g.vertex_val[5] = gs_in[0].position5;
    g.vertex_val[6] = gs_in[0].position6;
    g.vertex_val[7] = gs_in[0].position7;

    int n = tesselate_grid_cube(g);
}

```

---
Tags: unreal-4, clouds
---


# Question
Title: Is it possible to make smooth transitions between clips in the Unity legacy Animation component?
I'm trying to use the legacy Animation component for the UI and I can't find a way to make it go from one state to another smoothly. When using the Animator component the animated parameters change their values smoothly when go from one state to another if the transition duration parameter \> 0, but there doesn't seem to be anything like transitions/durations in the legacy Animation component, so it immediately changes the values. Is there a way to get smooth transitions with the legacy Animation?

# Answer
The animation component can interpolate between two animation clips with the script method `Animation.CrossFade`. When you want to transition from the current animation clip to another, you first have to register the clip with the animator using `AddClip`:

```
private Animation myAnimation;
[SerializeField] private AnimationClip secondClip;

void Start() {
    myAnimation = GetComponent<Animation>();
    myAnimation.AddClip(secondClip clipAsset, "second");
}

```

Now you can transition to this new clip with:

```
myAnimation.CrossFade("second", transitionTimeInSeconds);

```

There is also `CrossFadeQueued` which will wait with the transition until the current animation reaches the end of its current loop.

But if you have the requirement to have transitions between different clips, you might really want to consider to migrate from the legacy animation to the (not so) new state-based animation system. It's not just for humanoid characters.
> 1 votes

---
Tags: unity, animation, animation-controller, animation-states
---


# Question
Title: Prediction in deterministic netcode: Mixing predicted and non-predicted elements in display code. How do?
This one is a bit complex. So, I'm working on an FPS game that uses deterministic lockstep netcode, it can predict certain things like the player's own movement, weapon firing, and sounds. Entities outside the player aren't predicted, so other players, enemies, etc all have one state.

For prediction, there are two copies of the player's state, one for the predicted outcome, another is the "real" state. So, let's say we got `PlayerData_t realPlayer`, and `PlayerData_t predictedPlayer`.

The prediction works by running the same code as the real state, but with pointers changed to target our predicted struct, rather than the real one, and once the network catches up, the predicted state is rolled back to the new values of the real struct and replayed/corrected with this new information.

In this game, there's a member of `PlayerData_t` used for display-related code, like one for light flashes. Let's call this "flash". "Flash" is decremented in the drawing code to fade out the light relating to the flash. The drawing code obviously doesn't operate in lockstep with our sim. Any object can set a player's flash value, such as explosions.

In our display code, if we use `predictedPlayer->flash` as our source, only flashes from predictable code ever show up, so... like firing weapons. Since explosions aren't predicted, it never sets it (`realPlayer->flash` gets set). If we use `realPlayer->flash` as our source, flashes for firing the player's own gun, show up late (ie, when the network catches up).

If we do `predictedPlayer->flash = realPlayer->flash` just before rolling back and replaying/correcting the prediction, we get some nasty flicker, because our display code only decrements `predictedPlayer->flash`, while the sim sets `realPlayer->flash` and `predictedPlayer->flash`.

If we move our flash member to a new struct for display-related things, and modify that, we get flicker for another reason: Predicted code sets it, display code starts decrementing it, real code then sets it back again when the network catches up, it's then set back YET AGAIN when the rollback & replay happens.

So, what can I do? Is there some way I can merge both `realPlayer->flash` and `predictedPlayer->flash`, and have it only show once per occurrence? Hopefully, this is a clear enough explanation of what's going on. If not, I can try to clarify with some code snippets.

# Answer
> 0 votes
One solution would be to use only deterministic code and only show the action when it has been processed by the server. Of course, that's going to cause some latency issues but if you want a perfect simulation, that's the way to go.

That would mean that a shot that's been fired won't happen for the player unless it has already happened for the server.

If I were you, the only thing that would not need to be verified by the server to be seen would be the player's controllable actions. That way, the client is always very reactive, but only gets rollback when there's an issue coming from the server.

---
Tags: rendering, networking, movement-prediction
---


# Question
Title: Rollback netcode: how to avoid teleportation?
I've currently implemented rollback netcode with a central, authoritative server (wooh!). I'm running into issues where if players have zero input delay, the other players see them "teleport" to their locations once the clients receive the update.

Below is an example, assuming a 6 tick round-trip time (3 ticks to server, 3 ticks to clients) and both the client and server running at 60TPS.

1. Server is on T.
2. Client is enforced to always be simulating N steps ahead of its last known server frame. Let's assume it's hard-coded to T+3.
3. Client sends input at T+3 to "jump".
4. Server receives input at its T+3, simulates it, and sends it to other clients.
5. Other clients receive the T+3 input at T+6. The clients roll-back to the T+3 frame and simulate back to T+6 with the corrected input.

Step 5 causes us to lose drawing T+3, T+4, and T+5 accurately so it can look like the player "teleports" to their T+6 position. One way to solve this would be to add an input delay of 3 (client sends at T+3 for T+6), but I don't think this would scale well for clients with differing round-trip times and the input delay can feel rather bad.

How is this problem typically solved? I've watched the Overwatch + Rocket League rollback netcode talks and the great videos from Net\_ on YouTube, but nothing mentions how to handle smoothing out this portion.

# Answer
> 1 votes
As DMGregory said, Rollback is about blending the initial state and the new information coming from the player. You can also watch this video to learn more about how to blend animation.

---
Tags: algorithm, networking, multiplayer, realtime, movement-prediction
---


# Question
Title: How to check which code has destroyed or disabled a GameObject?
In legacy code, I need to check what caused the game object to be destroyed, disabled, etc.

Is there any way to trace or to place a breakpoint to check the call stack for why the game object became disabled?

# Answer
There is no native way to do this.

What you can do instead is create some extension methods something like this:

```
public static class DebuggingAids {

    public static HashSet<UnityEngine.Object> watchList = new HashSet<UnityEngine.Object>();

    public static void CheckedDestroy(this UnityEngine.Object target) {
        if (watchList.Contains(target) {
            // Place your breakpoint or debugging code here.
        }
        UnityEngine.Object.Destroy(target);
    }

    public static void CheckedSetActive(this GameObject target, bool active) {
        if (watchList.Contains(target) {
            // Place your breakpoint or debugging code here.
        }
        target.SetActive(active);
    }

    public static void CheckedSetEnabled(this Behaviour target, bool enabled) {
        if (watchList.Contains(target) {
            // Place your breakpoint or debugging code here.
        }
        target.enabled = enabled;
    }
}

```

Now search your codebase for any instance of the following patterns, and replace them:

* `Destroy(foo)` --\> `foo.CheckedDestroy()`
* `foo.SetActive(bar)` --\> `foo.CheckedSetActive(bar)`
* `foo.enabled = bar` --\> `foo.CheckedSetEnabled(bar)`

After you've done this, the static class above should be the only place using `Destroy`/`SetActive`/`.enabled` directly. Everything else will go through it as an intermediate.

By adding an object you care about to the `watchList`, `DebuggingAids.watchList.Add(foo)`, you can trap anything that tries to disable or destroy the object from script.

This won't catch disabling/destruction that happens on an assembly reload, scene load, or exiting Play Mode, but those should be fairly obvious to detect on their own.

You can use assertions or prepocessor directives to make it so your debugging code only runs in editor, so that these indirections compile away to nothing in a release build.
> 1 votes

---
Tags: unity, debugging
---


# Question
Title: Cannot retrieve accurate position of moving basepart
I am stopping a moving player model in its tracks and would like to get its position.

Here is my test:

```
target.HumanoidRootPart.Anchored = true
target.Humanoid.PlatformStand = true
while wait(5) do
 print('v1 => ' .. tostring(target:GetPrimaryPartCFrame().Position))
 print('v2 => ' .. tostring(target.HumanoidRootPart.CFrame.Position))
 print('v3 => ' .. tostring(target.HumanoidRootPart.Position))
 print('v4 => ' .. tostring(target.HumanoidRootPart:GetRenderCFrame().Position))
end

```
All four debug msgs agree on the target's position and never change. However, the position they agree on is **incorrect**. This can be verified in studio testing, under explorer, player model, humanoidrootpart, properties -\> Position.

While this is obviously related to the model's movement prior to this test method running, I am at a loss as to how I can retrieve the real position once the model is anchored.

I also tried removing the anchor and moving the model to verify that the position updates. And it does. So I know that I'm looking at the correct and updated instance.

How is it possible that these positions do not match?

# Answer
> 0 votes
The root problem is that the client and server are out of sync. Printing the position from a local client script shows the same position as the studio explorer. The server is not updating

The reason for this drift appears related to my use of anchoring and how that affects replication. This 2019 discussion brings up a few topics that I will look into:

https://devforum.roblox.com/t/cframe-not-replicating-while-character-is-anchored/247019/9

---
Tags: roblox, position
---


# Question
Title: Unity3d : Access the OnClick parameters of Button in a script
I have a button and I have attached another script "`PlaySound`" for this button, which plays audio on button click. As soon as the audio gets completed, I want to stop the animation which I am triggering here in `OnClick` of `Button`. How do I access the `Ellen` gameObject and `0` parameter which I set in the Inspector window (check the picture) in the `PlaySound` script

# Answer
Create a script with a `public Ellen ellen;` or whatever object you want to access. Then, in the script, check if the audio has finished playing and if it has, use `Animator.SetTrigger(x)`, where x is the stop animation parameter.

To be honest, I would do this all in one script with a function to start the audio that waits till the audio finishes then starts a second function to stop the animation. Then use that instead of Ellen
> 1 votes

# Answer
Internally, OnClick assignments are event subscriptions. On the surface, an event source should not know who is listening, so they are not meant to be accessed. Accessing the subscription list could be possible but it would be a hack that would introduce troublesome design.

For this problem, you need a script to hold a reference to the object `Ellen` and trigger the function for animation when the audio finishes playing. You can do it all where you play the sound, or use a separate class and make use of events or messaging.

You can arrange the flow below according to your design:

```
public class AudioVisualController : MonoBehaviour
{
    ...

    // Required if you stop the animation within this script.
    [SerializeField] private Ellen ellen;

    public void PlaySound()
    {
        audio.Play();
        Invoke("OnAudioFinished", audio.Length);
    }

    private void OnAudioFinished()
    {
        // Subscribe to this event from other class to stop animation.
        AudioFinished?.Invoke();

        // Or, stop the animation from here.
        ellen.Animator.SetTrigger(1);
    {

    ...
}

// If you use event subscription, stop the animation here.
public class SomeManager : MonoBehaviour
{
    ...
    [SerializeField] private AudioVisualController controller;
    [SerializeField] private Ellen ellen;

    private void Awake()
    {
        controller.AudioFinished += OnAudioFinished;
    }

    private void OnDestroy()
    {
        controller.AudioFinished -= OnAudioFinished;
    }

    private void OnAudioFinished()
    {
        ellen.Animator.SetTrigger(1);
    {

    ...
}

```
> 0 votes

---
Tags: unity, animation
---


# Question
Title: Move object from one position to another considering the colliders
I want to move object from one position to another but with one exception that the object should adjust its path according to colliders. The object is free to fly so it should consider colliders in its way and adjust its position accordingly. Currently I am doing it with `[MoveTowards][1]` function, lerp and coroutine but It ignore the collider and with it smoothly moved to another position. How should I intelligently adjust my path?

# Answer
If the obstacles are static, use a NavMesh.

If the obstacles are dynamic, you can use another larger collider around your object to determine if some safe distance to an obstacle is reached. Then, you can modify your heading and continue.
> 1 votes

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


# Question
Title: How to administer Bartle taxonomy of players survey
I made a game where I want to check how players act depending on the type of used minimap (minimal vs. path to next task is drawn etc). I came across the Bartle taxonomy of player types for this purpose.

I was able to find the questions data thanks to this question: Bartle taxonomy formula

But I struggle now on how to run this test with people. In the data set are 39 questions. @Trevor Powell mentions in his answer that this means an uneven split between the types:

> In the original question set (which is used verbatim in both of the links posted in the question), 'Socialiser' and 'Killer' are each available 20 times, while 'Achiever' and 'Explorer' are each only available 19 times. This biases test results slightly towards producing higher 'Socialiser' and 'Killer' values.

The online questionaires I find use only 30 questions like:

http://matthewbarr.co.uk/bartle/

http://matthewbarr.co.uk/bartle/index.php

I noticed that they have different questions on every run. Like it says on the Wikipedia page, they are randomly selected, and this matches what's on http://www.andreasen.org/bartle/ (you get redirected after 10 seconds).

If I want to get a player type for my participants, it seems odd to me that everyone gets different questions. My plan would be to select 30 questions and ask every participant the same questions.

What is the correct way to administer this survey and determine a player's Bartle type?

# Answer
> 1 votes
Social science is no exact science. So trying to implement a Bartle taxonomy test *correctly* is likely an endeavor which is as futile as it is pointless. You might want to focus on instead is to implementing an own variant of the test in a way which gives you results that are *useful for your particular use-case*.

So I would advise you to mostly ignore any question catalogs you find on the Internet and instead come up with your own which uses examples which are closer related to the design pillars, mechanics, hooks and themes of the game you developed or plan to develop. That will give you results which are far more useful to you, because they are closer to what kind of role a player would like to play in *your* game.

---
Tags: game-design, mmo, psychology, motivation
---