# Question
Title: How to Spawn GameObjects at Random Positions in Unity?
Hello GameDev Community,

I have a problem with this pice of code. If I start the "Game", it crashes right away. Probably is its the list of GameObjects or the foreach loop. I have no idea how I can solve the problem. Please don't be too strict with me \[...\]

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

public class TreeGeneratorScript : MonoBehaviour
{
// ####################################################################################################

// GameObject: Tree
public GameObject prefabTree;

public Vector3 minGroundPos;  // Vector3(  0, 1,  0)
public Vector3 maxGroundPos;  // Vector3(100, 1, 50)

// List of GameObjects with our Trees
public List<GameObject> treeList = new List<GameObject>();

// Number of attempts ( 100 )
public int numRunTry;

// Variables
GameObject newTree;
float distance;

// ####################################################################################################

void Start()
{
    // Instantiate a tree in the middle of the Scene
    newTree = Instantiate(prefabTree, new Vector3(50, 1, 25), Quaternion.identity);

    // Add GameObject to our List
    treeList.Add(newTree);

    // Call Method: SpawningTrees
    SpawningTrees();
}

// ####################################################################################################

void SpawningTrees()
{
    // Try 100 times to spawn a tree
    for (int i = 0; 1 < numRunTry; i++)
    {
        // Get a Random Position
        Vector3 randomSpawnPos = new Vector3(
            Random.Range(minGroundPos.x, maxGroundPos.x),
            1,
            Random.Range(minGroundPos.z, maxGroundPos.z)
        );

        foreach(GameObject tree in treeList)
        {
            // Calculate the distance between our Random Position and each tree from our list
            distance = Mathf.Sqrt( Mathf.Pow( (tree.transform.position.x - randomSpawnPos.x), 2) + Mathf.Pow( (tree.transform.position.z - randomSpawnPos.z), 2));

            // Check if the distance is smaller 12 between a tree and the Random Position
            if(distance < 12)
            {
                // Random Position is too close to our tree -> new Random Position
                break;
            }
            else if(distance >= 12 && tree == treeList.Last())
            {
                // Every tree from our list has a min distance of 12 to our Random Position

                // Instantiate the final tree
                newTree = Instantiate(prefabTree, randomSpawnPos, Quaternion.identity);

                // Add tree to our list of trees
                treeList.Add(newTree);

                break;
            }
        }
    }
}

```

After I run the code, it should look like this:

# Answer
Your problem is in your for loop :

```
for (int i = 0; 1 < numRunTry; i++)

```

1 is always less than numRunTry so loop never ends. Probably a typo and you meant

```
for (int i = 0; i < numRunTry; i++)

```

Correct that and it works fine:
> 1 votes

# Answer
I'm by no means equipped properly to answer this question, so forgive me if I am wrong. However, I notice in spawning trees method you are attempting to spawn 100 trees, it would appear? Have you tried just spawning a lesser amount to see if that is to many for it to handle or not?
> 0 votes

---
Tags: unity, gameobject, spawning
---


# Question
Title: Creating a background image with Photoshop for Unity
I'm making a home screen for my game. I don't know how to transfer a 2d image from Photoshop into a game that's on Unity. How do I import the image and make it visible in game? It’s a 3D game. I don't know what other information is relevant.

# Answer
> 1 votes
There are a number of ways of using a bitmap image as a backdrop in Unity, but the most straightforward way is to use the Unity UI system with an `Image` component.

1. Add a Canvas to your scene (GameObject -\> UI -\> Canvas). This will also add an EventSystem game object to your scene's hierarchy:

2. Add an Image as a child of your Canvas (GameObject -\> UI -\> Image):

3. Adjust the image to fill the entire screen, by setting the image's `RectTransform` component Anchor Preset to *stretch/stretch*, and setting the Left, Right, Top and Bottom to zero.

4. Import your background image from Photoshop (or any other image editing program) into your Unity project. Unity supports many different filetypes, including Photoshop native (.psd) but also .png, .jpg, .tif, .tga and on and on. Pro tip: Layered .psds imported into Unity remain fully editable as such in Photoshop.

To use a texture as an Image component source image, its Texture Type must be set to *Sprite (2D and UI)* in import settings.

5. Set the Source Image field of the Image component in your Canvas to this newly created sprite:

Violá:

---
Tags: unity, textures, sprites
---


# Question
Title: Unity LoadScene did not seem to work properly
My logic is simple: after conditions are met, display an image (an `Image` class instance) and restart the stopwatch. After a certain time, reload the scene. In a `MonoBehaviour` script I wrote:

```
if(stopwatch.ElapsedMilliseconds > sceneReloadTime)
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}

```

`sceneReloadTime` time was set to `3000`, which should be 3 seconds, but after displaying the image for 3 seconds, the image remains there and the scene did not seem to have been reloaded.

Out of confusion I put a breakpoint and used Visual Studio's debug tool, and confirmed that it has indeed entered the `if` and seems to have gone through `LoadScene`. I hit `continue` in VS and was led to a seemingly reloaded scene, but very dark as if the exposure has been tuned down to near zero.

This "dark world", however, only appears when I use VS debug and hit continue. If I play in Unity it never seems to reload and will be stuck on the image forever.

What could have gone wrong? Thank you.

# Answer
Instead of reloading the scene itself, load a small “helper” scene that then loads the main scene again. The helper scene could be a opportunity to present high scores etc.
> 1 votes

---
Tags: unity, c#, visual-studio
---


# Question
Title: Should in-game events (raids) be announced?
Many survival games such as Rimworld will announce when significant events happen in-game. For example, when a raid, a disaster or a significant event occurs, the game will send a notification and even allow the game to be paused for the played to read about what's about to happen.

I'm also making a procedurally-generated survival game where nights will be prime opportunities for terrifying night creatures to spawn. There might be a few of them spawning, or a whole pack of them capable of presenting a serious threat to the current playthrough.

My main priority is keeping the game immersion high, but I also think having the game announcing major events may create more tension and excitement for the players because they know something significant is about to happen. However, I'm worried that it might break immersion and realism and perhaps give away information that should've been discovered naturally (such as the player not knowing how many night creatures are about to attack, or when).

What would be the advantages and disadvantages of announcing certain events happening, and when should they be used?

# Answer
Announcing events has two purposes, and both boil down to giving the player the information they need when they need it.

One is to explain to the player what is going on. Rimworld, for example, is a game which lacks the visual language to tell the player that the block of rock which suddenly appeared on the map was a meteorite impact, or whether the group of people who just appeared at the edge of the map are here to trade or to fight. So the easiest solution is to simply tell the player what just happened, so they can properly contextualize what they see.

Another is to grab the players attention when it is required. A lot of disasters require that the player reacts to them immediately. When the player is currently micromanaging a complicated construction project on the east-side of their base, then they would not notice that a hostile raiding party appeared on the west-side a minute ago and that they already killed half of their people. Sure, you could try to train the player to regularly look around the map, and after a couple frustrating game-overs they might even start doing that. But making the player unable to focus on anything because they need to be always vigilant might not be the playstyle you are going for. So when an emergency situation occurs which requires that the player deals with it immediately, then the game should tell them.

Some disasters might require the players attention not just when they happen but even before. This is the case when the disaster requires that the player takes preparation. For example, an especially strong raid might warrant an early warning if no reasonable player can be expected to be prepared for it.
> 0 votes

# Answer
A balanced approach could be some in-game mechanism that lets the player know the event is happening. e.g. An item that tells the player if a pack of creatures are spawning or perhaps a change in lighting or music. This would allow for the player to receive the information without breaking immersion.
> 3 votes

---
Tags: game-design, procedural-generation, game-mechanics, random
---


# Question
Title: Why does Unity reload when I switch between branches in SourceTree?
I have decided to work with multiple branches (Art, mechanics, packages etc.) on SourceTree but I noticed that Unity reloads everytime I switch between branches and I can't access a prefab from another branch. Is my approach with branches wrong ?

# Answer
> 3 votes
When you switch branches, you are switching the contents of your Unity project. The reason you can't access the prefab from the second branch, is because it doesn't exist on that branch.

When you change the contents of a Unity project externally (such as via git), Unity reloads the changed assets.

Atlassian does a good job of explaining how git branches work: https://www.atlassian.com/git/tutorials/using-branches

---
Tags: unity, version-control, git
---


# Question
Title: Which AI should I use so as to avoid monsters AND chase bonus pills at the same time?
I'm trying to program an AI for a Pac-Man-like game, where I would be the Pac-Man and move according to two simple rules:

* move towards bonuses
* avoid monsters and being killed

I read that one can create a "fake AI" with Dijkstra maps (a.k.a. heat maps) such as the ones described in the very good article *Flow Field Pathfinding for Tower Defense*.

So, for each turn in my game, I have implemented these heat maps according to the aforementioned rules:

* **Flee map**

1. Add each monster as a source, and compute the Dijkstra map
2. Multiply by a negative factor (-1.2) to make repulsive instead of attracting sources
3. Rescan the cells and compute a new Dijkstra map (avoid being cornered)

* **Bonuses**

1. Add each bonus pill to the sources, and compute a Dijkstra map

The two maps seem fairly correct, however I can't manage to combine them together because this generates cases where the player (Pac-Man) is either stuck or not going in the right direction. I have tried for example to do such, but the results are not very good:

`movement_map = 0.9 * flee_map + 0.1 * bonus_map`

I also tried a single map with positive and negative weights for monsters and pills, but this does not seem to work either.

So my questions are:

* Are Dijkstra maps appropriate when trying to respect opposites rules (go to bonus pills, AND avoid monsters)?
* If not, which algorithm should be used? Otherwise, how can I combine, or at least, make these Dijkstra maps work together?

# Answer
How about combining your Dijkstra map logic with a fuzzy logic state machine for your-AI driven character that helps the AI prioritize which goal it is pursuing?

The idea is, once the AI is say, fleeing, it continues to "flee" (using the Dijkstra map for flight) until it has sufficiently "fled" (this is where the fuzzy logic comes in.) Same for pursuing pills -- it pursues until it gobbles or the pill has "eluded," or monster threat has reached a threshold (fuzzy logic again).
> 1 votes

# Answer
Use Collaborative Diffusion. It is also a hill-climbing approach, though a little more modernised.

* It has already been successfully implemented for Pacman.
* It combines attractance & avoidance maps into one (for each AI side - in your case, ghosts).
* It supports multiple entities avoiding each other by each creating its own repulsion / avoidance field within the global map.
* There is no need for head-scratching heuristics as in A\* and its derivative algorithms, and it works well for small games with a limited number of agents / entities.

The original paper is here, and is fairly easy to follow.
> 1 votes

# Answer
This might be a matter of how you design your influence maps.

A nearby enemy is a very high priority, but an enemy further away isn't. So the influence map of enemies should start with a very high value, but then fall off rather quickly.

A bonus pill is an objective which is worth working towards even if it is further away, but not worth dying for. So it should start with a low value, but fall off very slowly.

Another thing you can do is modify the value of a power-pill depending on the proximity of threats. A power-pill with an enemy nearby might be too dangerous to pick up, while an unguarded one is a great target of opportunity. So you could scale the influence of a power-pill anti-proportional to the distance to the enemy closest to it.
> 1 votes

---
Tags: ai, path-finding, dijkstra
---


title: Show colliders in a build game in Unity

text:
# Question
Title: Show colliders in a build game in Unity
Is there a way to show all colliders 2D in a a released game at once? I am making a 2D game in Unity and have to show all colliders to the player. Can I use Gizmos?

# Answer
Gizmos are only visible in the Editor, so that is not a solution.

Instead, you can render the colliders or (simulate rendering them) any number of ways.

## BoxCollider2D

If your 2D colliders are boxes, this is pretty simple -- use a `LineRenderer` to render the collider's outline.

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

[RequireComponent(typeof(BoxCollider2D))]

public class DrawBoxCollider2D : MonoBehaviour
{
    [SerializeField] private GameObject linePrefab;
    LineRenderer lineRenderer;
    BoxCollider2D boxCollider2D;

    void Start()
    {
        lineRenderer = Instantiate(linePrefab).GetComponent<LineRenderer>();
        lineRenderer.transform.SetParent(transform);
        lineRenderer.transform.localPosition = Vector3.zero;
        boxCollider2D = GetComponent<BoxCollider2D>();

    }

    void Update()
    {
        HiliteBox();
    }

    void HiliteBox()
    {
        Vector3[] positions = new Vector3[4];
        positions[0] = transform.TransformPoint( new Vector3(boxCollider2D.size.x / 2.0f, boxCollider2D.size.y / 2.0f,0));
        positions[1] = transform.TransformPoint(new Vector3(-boxCollider2D.size.x / 2.0f, boxCollider2D.size.y / 2.0f,0));
        positions[2] = transform.TransformPoint(new Vector3(-boxCollider2D.size.x / 2.0f, -boxCollider2D.size.y / 2.0f,0));
        positions[3] = transform.TransformPoint(new Vector3(boxCollider2D.size.x / 2.0f, -boxCollider2D.size.y / 2.0f,0));
        lineRenderer.SetPositions(positions);
    }
}

```

Here's the set up to get this to work:

Sprite Setup:

Line Rendererer Prefab:

In action:

## PolygonCollider 2D

Polygon colliders are only a little more complex. They can consist of several paths (to allow for holes); to make the code easy to follow and sheer expediency, my example will make the dumb assumption that there is only one path in the collider:

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

[RequireComponent (typeof(PolygonCollider2D))]
public class DrawPolygonCollider2D : MonoBehaviour
{
    [SerializeField] private GameObject linePrefab;
    LineRenderer lineRenderer;
    PolygonCollider2D polygonCollider2D;

    void Start()
    {
        lineRenderer = Instantiate(linePrefab).GetComponent<LineRenderer>();
        lineRenderer.transform.SetParent(transform);
        lineRenderer.transform.localPosition = Vector3.zero;
        polygonCollider2D = GetComponent<PolygonCollider2D>();

    }

    void Update()
    {
        HiliteCollider();
    }

    void HiliteCollider()
    {

        var points = polygonCollider2D.GetPath(0); // dumb assumption for demo -- only one path

        Vector3[] positions = new Vector3[points.Length];
        for(int i = 0; i < points.Length; i++)
        {
            positions[i] = transform.TransformPoint(points[i]);
        }
        lineRenderer.positionCount = points.Length;
        lineRenderer.SetPositions(positions);
    }
}

```

More info on PolygonCollider2D

Setup is the same; Result are like so:
> 5 votes

---
Tags: unity, collider, build
---


# Question
Title: How can I apply steering behaviors to a car controlled with turning and acceleration?
I feel like I've got my head around steering behaviors, but I've having trouble applying them to a car. The steering behaviors return forces that one could apply to an object that can move in any direction, but a car can essentially only move forward and turn. I'm having trouble determining how hard the car should turn or how much it should accelerate forward based on the steering force. How can I translate a steering force into the car's input?

# Answer
You will have to calculate the desired input (steering and throttle) based on:

1. The relative direction of the desired velocity when compared to the current velocity (for steering input)
2. The relative magnitude of the desired velocity when compared to the current velocity (for throttle input)

---

For calculating steering input, we need to calculate the amount of steering it will take to rotate the current velocity vector in the direction of the desired velocity vector based on the angle of steering at maximum lock in radians (`maxSteerAngleInRad`).

Assuming full left and right lock is represented by `-1` and `1` respectively, the steering input can be calculated as follows (`desired` and `current` are the desired and current velocity vectors):

```
fullSteers = acos(dot(desired.normalized, current.normalized)) / maxSteerAngleInRad
steer = sign(dot(leftperp(desired), current)) * fullSteers

```

where `leftperp` for a 2D vector `(x, y)` is given as `(y, -x)`. The `sign` expression serves to provide the direction (left or right) to steer in. If `desired` is to the left of `current`, the expression returns `-1` and `1` if it is to the right.

If the steering input is reversed (i.e. positive values represent left and negative values represent right), simply use the right perpendicular (`(-y, x)`) instead of the left or simply negate the value of `steer`.

To get rid of the `acos` call, you can use a more inaccurate albeit more performant approach wherein `fullSteers` is the quotient of the normalized *cross* products (where `cross(a, b) = a.x * b.y - a.y * b.x`) of the desired and current velocities, and the sine of `maxSteerAngleInRad` (which can be precalculated).

`steer` should also be clamped between `-1` and `1` if your vehicle input system does not do so.

---

For calculating throttle input, we simply need to accelerate if `desired.magnitude` (desired speed) is more than `current.magnitude` (current speed), and brake if it is the other way around. You may also want to choose intermediary throttle values based on the speed difference and the vehicle throttle response.
> 3 votes

# Answer
If you need to figure out which way to turn the car's wheels, then taking the determinant of a target position(that's been subtractad from the car's position) and the car's direction will work.

source
> 0 votes

---
Tags: ai, path-finding, steering-behaviors, car
---


# Question
Title: How do I make sure the order of my vertices are always clockwise when creating new triangles?
In 2D I'm trying to insert a new vertex in my mesh and creating new triangles using that new vertex sort of like the red vertices in the picture shown:

However, I'm having trouble with figuring out how to order the vertices in the triangles array so that they are ALWAYS, no matter what situation, clockwise and render properly.

# Answer
No matter where you place your new vertex, you will split your triangle into two triangles, each of which will take two consecutive vertices from the original triangle (in the same consecutive order) and one vertex will be the new insertion, replacing the vertex that we "removed".

Splitting along the edge between vertices P and Q with a new vertex N, you make two triangles, one that replaces P by N and one that replaces Q by N.

So let's say we have triangle A B C (in clockwise order), and we want to insert a new vertex N...

* Between A & B:
    + N B C (replace A with N)
    + A N C (replace B with N)
* Between B & C:
    + A N C (replace B with N)
    + A B N (replace C with N)
* Between A & C:
    + N B C (replace A with N)
    + A B N (replace C with N)

One way to verify that this always has the same winding as the original triangle is to consider the cross product. Let's fix an ordering of the vertices A B C so that the new vertex N is inserted between A and B. The winding of this triangle is determined by the direction of the cross product (A - C) x (B - A) or (B - A) x (C - B) (among other equivalent formulations).

* One new triangle's winding is (A - C) x (N - A), and (N - A) is parallel to (B - A) by construction, so the cross product points in the same direction as (A - C) x (B - A) and the winding is the same.
* The other new triangle's winding is (B - N) x (C - B), and (B - N) is parallel to (B - A) by construction, so this cross product points in the same direction as (B - A) x (C - B), and so the winding is also the same.
> 1 votes

---
Tags: unity, vertex
---


# Question
Title: unity JsonUtility.ToJson returns empty string
I am trying to use Unity's built in json serialization. It produces empty string. I do not understand why. (I was trying to use NewtonSoft Json.Net but that wasn't working either even though I was following instructions).

Here's the serialization code:

```
public class Player : MonoBehaviour
{
    void Start ()
    {

        Mission a = new Mission()
        {
            Id = 1,
            Name = "Speak to the Farmer",
            State = MissionState.OnGoing,
            Parent = -1,
            Type = MissionType.Main
        };

        string json = JsonUtility.ToJson(a);
        System.IO.File.WriteAllText("missions2.json", json);
    }
}

```

Here's the `Mission` class:

```
[Serializable]
public enum MissionState
{
    NotStarted,
    OnGoing,
    Finished
}

[Serializable]
public enum MissionType
{
    Main,
    Sideline
}

[Serializable]
public class Mission
{
    public Mission()
    {
        Parent = -1;
    }

    public int Parent { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public MissionState State { get; set; }
    public MissionType Type { get; set; }
}

```

here's the output: `{}`

There are no exceptions thrown. The file missions2.json is created. But the data is as shown above. What is wrong that the serialization produces nothing?

Thnx Matt

# Answer
Unity's JsonUtility only serializes public fields.

```
//  you don't even need the Serializable attribute when using JsonUtility
public class Mission {
    public int ID; // just a public field, no SerializeField attribute needed either
}

```

You should use Newtonsoft's Json library if you need more flexibility.
> 2 votes

# Answer
Unity do not serialize properties. You need to have simple fields in order to serialize class. It is one of the limitation of jsonUtility.

In Short,

**Use**

```
 public int Parent;

```

**instead of**

```
 public int Parent { get; set; }

```

in your class .

Otherwise use Newtonsoft.json plugin.
> 7 votes

# Answer
if I recall correctly, when you serialize a C# class to JSON, it serializes members, not properties (even if by {get; set;} the compiler creates the members). You can try by marking the members as serializable with \[SerializeField\] or public access (you can still use C#'s properties to encapsulate your class/structure):

```
[Serializable]
public class Mission
{
    public Mission()
    {
        Parent = -1;
    }

    [SerializeField] private int Parent;
    [SerializeField] private int Id;
    [SerializeField] private string Name;
    [SerializeField] private string Description;
    [SerializeField] private MissionState State;
    [SerializeField] private MissionType Type;
}

```

Hope it helps.
> 5 votes

# Answer
I think you should add `public` to each property.

example:

```
[Serializable]
public class Mission
{
    public Mission()
    {
        Parent = -1;
    }

    [SerializeField] public int Parent;
    [SerializeField] public int Id;
    [SerializeField] public string Name;
    [SerializeField] public string Description;
    [SerializeField] public MissionState State;
    [SerializeField] public MissionType Type;
}

```
> 0 votes

# Answer
I think the problem is that you're calling the JSON operation from MonoBehaviour... I had a similar problem, so I created a static class to handle this, calling a function like `SaveMission()` and it worked.
> 0 votes

# Answer
change from

> **public int Parent { get; set; } public int Id { get; set; }**

to

> **public int Parent; public int Id;**
> -1 votes

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


# Question
Title: Multiplayer RPG allowing offline solo play using server signed replays - how can you cheat?
**What exploits does my system allow for that I can't solve or did not account for?**

I'm researching on a design for multiplayer RPG that can safely allow players to have their character files and play solo offline and reliably check they haven't cheated using fully deterministic game engine, action history (replays) and cryptographic signatures. I do this in attempt to deliver much wanted from players true ownership of their characters, lag free gameplay and cheat-free economy at the same time.

So far I have established the following facts and processes:

1. **FACT**: The game is fully deterministic with life-long RNG seeds embedded in characters upong creation.
2. **FACT**: Game records and replays user actions (not keystrokes and mouse clicks, but rather "attack enemy ID-42". Game client CD-KEY hash is embedded in each action sequence between saves
3. **EVALUATE AND SIGN**: After offline solo play, character file and action history are uploaded to server, where action history is replayed headlessly and end-state is compared with candidate-end-state. If they match, the end-state is signed with X509 private key and signature is downloaded and appended to the character file. Action history is required for play sessions since last signed state.

1. **FACT**: Signing requires account authentication to prove owning the character. Characters are tied to accounts online, but can be shared between players for offline play.
    2. **FACT**: Hashed CD-KEY of the client is embedded in the character, so the server knows on which game client the play session happened
4. **VERIFYING**: When attempting multiplayer, either LAN or developer-hosted, character signatures are verified. If latest state is not signed - go to step 3. Only signed characters can participate in official servers.

1. If a character loses action history for whatever reason they can still play solo offline, but not on official servers.
    2. Illegal actions like use a wrong ID or attack an enemy outside your reach invalidate the action history and the character is not signed
    3. Server tracks how long (in game ticks) a CD-Key has played and verify if it's possible to have played that much since the CD-Key is issued. You could not have played 3000 hours on a CD-Key that has been issued 1000 hours ago. With multiple CD-Keys, their play-time-budget is verified for overlapping play-time with other characters that used it. E.g. if a CD-Key has been issued 1000 hours ago, someone has played for 700 hours using it and the candidate applies for a 500 hours-long play time then the candidate is rejected (500+700 = 1200 \> 1000).
5. **FACT**: Trade is only allowed online (no LAN) to cut off many hard-to-solve cheat scenarios.

Assume common sense security like logging, network setup and server configuration has been planned for.

## Issues I have accounted for

### Reverse-engineering

Most concerning issue I see with offline solo play is that hackers will completely reverse-engineer the file format and/or the game and forge game-valid godly characters, ruining the economy and the community. **Solution**: This takes very long time and concentrated effort from experienced professionals to do.

1. Small patches and updates can force you to constantly do RE work and if consistent enough, RE clients may never be up-to-date.
2. If the incentive doesn't come (game is not popular enough, gameplay offers what you would cheat for anyway, cheats are hard to monetize) hackers won't spend the effort.
3. Anyway, assuming they could produce legit characters the damage to the economy (for which I care the most) would be minimal because CD-Keys play-time budget (fact 4.3) would limit how much hours the character could have played. Furthermore, since the game is deterministic, the character will only have whatever items the RNG says (and they cared to stash). If a character is destined by RNG to get lucky at kill number 294 942 953 291 it will happen exactly then and that may be way past the timeline that has been forged. Even using oldest possible CD-Keys won't help since they would have play-hours logged already. This also discourages exploring alternate decision making to hit the best RNG outcome.

### Impersonation and theft

Cheater may acquire with or without permission somebody elses character file, then transfer his belongings or attempt to impersonate him online. Either of these won't work, because you need to authenticate online.

### Branching

Cheater may copy character file to duplicate the items, but we established trade can only happen online for that reason. Trading on LAN is *possible* but too problematic for this very reason and is thus unavailable

### Character file size

A character state would only be few kilobytes without action history or states from the past. However, I have estimated a full year of non-stop playing - 96 hours a week with APM of 200 and action being 17 bytes (which is pretty generous) the file would be ~1GB which can be problematic for storage on the server. While charactrs only need their last signed state (few KB) and action history since (~180 KB/h), the server needs it all for forensics and analysis. E.g. server may want to check players for a known bot signature.

### Botting (unsolved!)

Storing replay data can be very helpful for identifying botting. However, botters have the same edge against the developer that the developer has against reverse-engineers - can consistently change their behavior footprint and make very hard to detect. The best ones would only read game memory or even screen colors to identify game state and simulate player input at the OS level which is honestly untraceable.

# Answer
A useful mantra to bear in mind is "**the client is in the hands of the enemy**".

*Any capability* that you build into the client that can run offline is one that you have delivered in a gift-wrapped package to anyone who wishes to hack the game.

If the client is capable of producing a valid play history that passes muster for server inspection, then **a hacked client is *also* capable of producing a valid play history** that similarly passes muster. And it can do it using *simulated* gameplay inputs and a forged clock, rather than real human input spanning real time — stepping your game logic as fast as the CPU can go.

(By a forged clock, I don't mean that they can run ahead of real time in the long run, but they *can* compress a full day's worth of play for their daily server check-in into some minutes of execution time, allowing them to farm the game without devoting a machine to a single account 24/7)

**They might not even need to reverse engineer or understand your code deeply** to do this. They could just call into the very same functions that run your game loop and execute them as black boxes with false input. Patching the game will not slow them down for long, because they don't need to reverse engineer the whole patch, just update their hooks to call / inject false input into the latest client you gifted them. If you support the old version for a few days' overlap to accommodate honest players who were playing offline around the transition, then by the time the new version becomes mandatory the hackers will likely have had plenty of time to adapt.

Obfuscating your input/time handling in new ways for each patch to try to fend this off is likely to be a losing game — barely a speedbump to a determined hacker, while creating risks of introducing new bugs for the majority of honest players.

The hackers *are* limited by how fast their total character progress can accrue on any one account/key, relative to server time between validations, but **that's still a high bar compared to typical human play investment**. If you've designed your game for the bulk of the audience to play 2-3 hours daily, simulated gameplay that uses all 24 hours in a day will see a character progress 8-12x faster than typical human efficiency.

You can add artificial limits, like mandating that more than 8 hours of play in a calendar day will be considered a bot, but that will catch some human players who just happen to play marathon sessions, while still allowing bots to progress 2-4x faster than typical humans for zero effort for their operator. There will be a market for players who would like to progress twice as fast without investing their own time/attention/skill.

**Not to downplay what your proposed method achieves**: restricting a hacker from unlimited / infinite progression rate per account down to a single-digit multiple of human efficiency is still significant and valuable. In one sense, a reduction from infinity to *any* finite value is an infinite win!

**But it's not enough to stop cheating**. Even progressing 20% faster than average — or being able to run multiple accounts in parallel without supervision — may be valuable enough to attract bot-users. **If the incentive is there to progress characters faster than casual play, the system you have proposed will not stop a cheater from exploiting it.** And the more enticing or prestigious you make the rewards in your game to please your honest players, the more you incentivize dishonest players to use bots to achieve those rewards at lower effort.

(You could try to artificially inflate the processing cost of each tick to reduce the time savings for folks compressing their play or farming multiple accounts by some degree, but this will mostly manifest as worse performance and battery life for your honest player majority, and higher server costs to do the validation, while not dissuading any hacker with a smart trick to to bypass it or enough compute resources to burn through it, so this too I would suggest is a losing game)

**The best bang for your buck in this system** is probably the recording and server-side analysis of play history. You could actually skip *all* the other clever signing and validation effort, and instead just run offline analysis of the history to find patterns and periodically mass-ban accounts that show unrealistic behaviour — according to a shifting definition of "unrealistic" that lives in your server-side analysis process, invisible to hackers. This denies a hacker the ability to get instant feedback from your server via its signature, validating whether their latest tweak has fooled it, making it much harder for them to isolate what telltale is giving them away. For more on this, see How to prevent automation-type cheating?.

---

As an aside, one other exploit is possible here due to the **lifelong deterministic RNG seed** per client. A hacker who reverse engineers your RNG code can copy the current RNG state and make many rolls on their copy, **using it as an oracle about future random outcomes**.

* When a "bad" roll is fated to come up next, they can make their character take an action that uses up an RNG roll in a harmless way — like playing a randomized taunt or other bark. They can know when not to spend mana/stamina on an attack that's going to miss, and when to take a long shot attack that's fated to roll a critical.
* They can know what boss move is coming up next, and react to it faster than a player who has to observe the animation/sounds for themselves.
* When rolling a procedural dungeon instance, they can know in advance what challenges and rewards it will offer, and abort and re-start or churn the RNG on quick randomized actions until they get the optimum one for their objective, skipping any sub-par runs.
* They can predict in advance when the "good" rolls are coming up on the horizon, so they can sequence their play so that these ideal rolls land exactly on important loot drop events, getting that epic item on their first try.

Used strategically, this can allow a hacker to progress faster than the basic time math above would suggest, despite the gameplay time validation that your server does, by **emulating an *exceptionally, improbably* lucky player**, who technically isn't breaking any gameplay rules.

You can make this some of these tricks harder / less beneficial by maintaining multiple RNG states for different purposes. Say one RNG state for "boss loot" that's not advanced by any other action in the game, limiting the rate at which the player can churn this RNG to the rate at which they can grind the fastest boss that uses it. Or you can use a biased randomizer that, say, has only one winning ticket in the hat per calendar day. But they still have perfect knowledge about what roll is coming up next, letting them strategically switch their play to get the optimal result from the hand that fate has dealt them - giving them a potential edge over a player who lacks this information to optimize their play pattern.

Being able to predict future attacks / hits / misses / criticals - and the exploitation of this knowledge for gameplay advantage - is unfortunately a necessary consequence of your deterministic model. But it's still a degree better than allowing players to forge a history where bad rolls never happen at all.
> 6 votes

---
Tags: multiplayer, client-server, rpg, anti-cheat, single-player
---


# Question
Title: How to fix animation script so that humanoid character holds their weapon
I am trying to follow this tutorial video about setting up an third-person shooter character in Unity.

But my character will not hold their weapon. I'm also getting the following warnings in my project:

> Assets/Unity-1/unity-1/player/playerAnimation.cs(8, 23): warning CS0649: Field \`playerAnimation.aimMask' is never assigned to, and will always have its default value.
>
> Assets/Unity-1/unity-1/player/playerAnimation.cs(16, 23): warning CS0414: The private field \`playerAnimation.chestBone' is assigned but its value is never used.
>
> Assets/Unity-1/unity-1/player/playerLocomotion.cs(12, 19): warning CS0414: The private field \`playerLocomotion.aimedWalkSpeed' is assigned but its value is never used.

How can I fix this?

Here are the scripts that the warnings complain about:

Player Animation:

```
/// <license>
/// Copyright(c) 2020 www.GameDevine.com
/// </license>
///
using UnityEngine;

public class playerAnimation : MonoBehaviour
{
   private LayerMask aimMask;
   private playerLocomotion playerLocomtion = null;
   private playerCamera playerCamera = null;
   private MovementCalculator movementCalculator = null;
   private playerWeapon playerWeapon = null;

   private Animator animator = null;
   [System.NonSerialized] public bool readyToMove = true;
   private Transform chestBone = null;
   [System.NonSerialized] public Vector3 trgetPoint = Vector3.zero;

   private float handIkSpeed = 10;
   private Transform rHandIk = null;
   private Transform lHandIk = null;
   private Transform rElbowIk = null;
   private Transform lElbowIk = null;

   private void Awake()
   {
      playerLocomtion = GetComponent<playerLocomotion>();
      playerCamera = GetComponent<playerCamera>();
      movementCalculator = GetComponent<MovementCalculator>();
      animator = GetComponent<Animator>();
      playerWeapon = GetComponent<playerWeapon>();
      rHandIk = new GameObject("rhik").transform;
      lHandIk = new GameObject("lhik").transform;
      rElbowIk = new GameObject("reik").transform;
      lElbowIk = new GameObject("leik").transform;
      Transform p = animator.GetBoneTransform(HumanBodyBones.Chest);
      rHandIk.parent = p;
      lHandIk.parent = p;
      rElbowIk.parent = p;
      lElbowIk.parent = p;
  }
  public void InitializeWeapon()
  {
     if(playerWeapon.weapon != null)
     {
        if (!rHandIk)
        {
           rHandIk = new GameObject("rhik").transform;
        }
        if (!lHandIk)
        {
           lHandIk = new GameObject("lhik").transform;
        }
        rHandIk.parent = playerWeapon.weapon.model;
        lHandIk.parent = playerWeapon.weapon.model;
     }
  }

  private void Update()
  {
     trgetPoint = GetAimTarget(50);
     animator.SetBool("Crouch", playerLocomtion.crouched);
     animator.SetBool("aimed" , playerLocomtion.aiming);
     animator.SetBool("grounded", playerLocomtion.grounded);
     animator.SetFloat("moveX", movementCalculator.Movement.x);
     animator.SetFloat("moveY", movementCalculator.Movement.z);
     switch (playerLocomtion.MoveType)
     {
         case 1:
               animator .SetBool("Walk" , true);
               animator .SetBool("Sprint", false);
               animator .SetBool("Run" , false);
               break;
         case 2:
               animator.SetBool("Walk" , false);
               animator.SetBool("Sprint", false);
               animator.SetBool("Run" , true);
               break;
         case 3:
               animator.SetBool("Walk" , false);
               animator.SetBool("Sprint", true);
               animator.SetBool("Run" , false);
               break;
         default:
              animator.SetBool("Walk" , false);
              animator.SetBool("Sprint", false);
              animator.SetBool("Run" , false);
              break;

       }
       readyToMove = !animator.GetCurrentAnimatorStateInfo(0).IsTag("Transition");
    }
    private Vector3 GetAimTarget(float range)
    {
       Ray ray = Camera.main.ScreenPointToRay(new Vector2(Screen.width / 2, Screen.height / 2));
       ray.origin = playerCamera.pivot.position;
       RaycastHit hit;
       if(Physics.Raycast(ray, out hit, range, aimMask))
       {
          return hit.point;

       }
       else
       {
          return playerCamera.pivot.position + playerCamera.main.forward.normalized * range;
       }

    }
 }

```

Player Locomotion:

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

public class playerLocomotion : MonoBehaviour
{
   private float walkSpeed = 4f;
   private float runSpeed = 7f;
   private float sprintSpeed = 10f;
   private float aimedWalkSpeed = 4f;
   private float crouchWalkSpeed = 3f;
   private float rotateSpeed = 10f;
   private float aimedRotateSpeed = 20;

   private playerCamera playerCamera = null;
   private playerinput playerinput = null;
   playerAnimation playerAnimation = null;
  [NonSerialized] public bool grounded = true;
   private float movement = 0f;
   private int moveType = 0;
  [NonSerialized] public bool crouched = false;
  [NonSerialized] public bool aiming = false;

   public int MoveType
   {
      get
      {
         if (movement < 0.1f)
         {
            return 0;
         }
         else
         {
           return moveType;
         }
     }
  }

  private void Awake()
  {
    playerCamera = GetComponent<playerCamera>();
    playerinput = GetComponent<playerinput>();
    playerAnimation = GetComponent<playerAnimation>();
  }

  private void Update()
  {
     float ver = playerinput.vertical;
     float hor = playerinput.horizontal;
     if (!playerAnimation.readyToMove)
     {
        ver = 0;
        hor = 0;

     }
     if(playerinput.crouch && grounded && !playerinput.sprint)
     {
       crouched = !crouched;
     }
     movement = Mathf.Clamp01(Mathf.Abs(hor) + Mathf.Abs(ver));
     if (grounded)
     {
        Vector3 cameraDirection = playerCamera.main.forward * ver;
        cameraDirection += playerCamera.main.right * hor;
        Vector3 dir = Vector3.zero;
        if (playerinput.jump)
        {

        }
        else
        {
            if (aiming)
            {

            }
            else
            {

               #region Rotation
               cameraDirection.Normalize();
               cameraDirection.y = 0;
               if(cameraDirection == Vector3.zero)
               {
                  cameraDirection = transform.forward;
               }
               Quaternion quaternion = Quaternion.LookRotation(cameraDirection);
               Quaternion targetRotation = Quaternion .Slerp (transform .rotation ,quaternion, Time.
               deltaTime * movoement * rotateSpeed);
               transform.rotation = targetRotation;
               #endregion

               #region Movement
               float speed = runSpeed;
               moveType = 2;
               if (playerinput.sprint)
               {
                  speed = sprintSpeed;
                  moveType = 3;

               }
               else if (playerinput.Walk)
               {
                  speed = walkSpeed;
                  moveType = 1;
               }
               if (crouched)
               {
                  speed = crouchWalkSpeed;
               }
               Vector3 targetPosition = transform.forward * movement * speed / 100;
               targetPosition.y = 0;
               transform.Translate(targetPosition, Space.World);
               #endregion

           }

       }
       else
       {

     }
  }

}

```

Player weapon:

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

public class playerWeapon : MonoBehaviour
{
    public Weapon weapon = null;
    private playerLocomotion playerLocomotion = null;
    playerAnimation playerAnimation = null;
    playerCamera playerCamera = null;
    public float moveSpeed = 10;
    public float rotateSpeed = 10;
    private Weapon.Pose pose = Weapon.Pose.stndingNormal;
    public Weapon.Properties.Pose poseData = new Weapon.Properties.Pose();

    private void Awake()
    {
        playerCamera = GetComponent<playerCamera>();
        playerAnimation = GetComponent<playerAnimation>();
        playerLocomotion = GetComponent<playerLocomotion>();

    }

    private void Satart()
    {
        if (weapon)
        {
            Initialize();
        }
    }

    public void Initialize()
    {
        Initialize(Vector3.zero);
    }

    public void Initialize(Vector3 zero)
    {
        weapon.transform.parent = GetComponent<Animator>().GetBoneTransform(HumanBodyBones.Chest);
        weapon.transform.localPosition = Vector3.zero;
        weapon.transform.localEulerAngles = Vector3.zero;
        poseData = weapon.GetPose(pose);
        weapon.model.localPosition = poseData.pose.position;
        weapon.model.localRotation = poseData.pose.rotation;
    }

    private void Update()
    {
        if (!weapon)
        {
          return;
        }
        if (playerLocomotion.crouched)
        {
            if (playerLocomotion.aiming)
            {
              pose = Weapon.Pose.crouchedAimed;
            }
            else
            {
              pose = Weapon.Pose.crouchedNormal;
            }

        }
        else
        {
           if (playerLocomotion.aiming)
            {
              pose = Weapon.Pose.standingAimed;
            }
            else
            {
              pose = Weapon.Pose.stndingNormal;
            }
        }
        poseData = weapon.GetPose(pose);
        if(weapon.model.position != poseData.pose.position)
        {
          weapon.model.position = Vector3.Lerp(weapon.model.position, poseData.pose.position, moveSpeed * Time.deltaTime);
        }
        if(weapon.model.rotation != poseData.pose.rotation)
        {
          weapon.model.rotation = Quaternion.Lerp(weapon.model.rotation, poseData.pose.rotation, rotateSpeed * Time.deltaTime);
        }

    }
}

```

# Answer
In the class playerWeapon, you have this method:

```
private void Satart()

```

I think this is supposed to mean `Start`. The Start method gets executed automatically on the first frame of the objects existence, but you have to spell it correctly. When you misspell a Unity event method, then it won't get recognized by the engine and the engine won't call it.

The result is that `Initialize` won't get called either, which means that the weapon model never gets parented to the armature of the character.

I don't know what IDE you are using for editing your code, but I would recommend Visual Studio 2019. When you create a Unity event method, then it will show a small Unity-icon above it. When you misspell the method name, then that icon won't show up and you get a warning instead telling you you created a private method which is not used anywhere.

---

The warnings you receive about unused variables appear to be unrelated to this particular problem. I would assume that you were told to create those variables in preparation of features which come later in the tutorial you are following.

Although if your character has a problem with aiming at things you are pointing at, then the first one "`playerAnimation.aimMask` is never assigned to" might be worth investigating. The value is later used in the method `GetAimTarget` to determine what colliders are considered valid objects to aim at via `Physics.Raycast`.
> 2 votes

---
Tags: unity, c#, animation, shooter, third-person-view
---


# Question
Title: Unknown challenges in Game Text Localization
Welcome to the most boring part of game development but everyone loves to see games adapted to their native language.

I have seen companies going nuts over this part of game development and I fully understand why. There's a package in Unity to do this. I am using Cocos creator 3.0. I am considering writing my own simple class. Here's my plan: I will convert every single word using Google Translate and prepare an Excel sheet or JSON, load these key values for different languages in a data structure and the user can convert this with the help of a Singleton class. I have a question though, is this good enough or there are problems which I am not aware of? Because I am getting the feeling that it's not that easy.

# Answer
> 2 votes
**Google Translate is not a localization tool**, and the method you proposed will not give you a good translation.

An automated translation cannot understand differences in **context**. Let's take the single word "back" displayed on a button in your UI. Does this mean...

* "Return to the previous screen/state" (like navigating a multi-screen UI, or unpausing and returning to gameplay), which we might translate into French as "retour"
* "Switch to the rear side of this object" (like switching between front and back designs for a shirt you're customizing), which we might translate as "côté arrière"
* "Invest and become a backer of this project/cause" (like supporting a Kickstarter or charitable project), which we might translate as "soutenir" or "financer"

...etc. And this is for just one common word translated into one language. Multiply this uncertainty by all the words in your game, by all the languages you want to support. If you automatically substitute word by word, you're playing Russian Roulette, and eventually you will get the wrong interpretation of a word somewhere, or they'll chain together into gibberish.

(Real-world example of this from my own recent experience: I have a student who sometimes leans on automatic translation for in-class discussions. Unfortunately the translator seems to translate "life amount", as in HP/Health Points, into "blood volume", which has a significantly more gruesome sound to an English-speaker!)

And that's not even talking about subject-verb agreement, gendered languages, or the variety of plural rules that can also change which specific form we'd translate to based on nearby words/values.

And it's saying nothing about voice and tone, matching the style of communication in your game to the right level of formality or casualness for its brand or the character who's speaking.

Your translation should be done at the granularity of a **complete passage of text**, not word by word. Say an entire heading or paragraph, or an entire message spoken by a character.

**Each place the same text occurs in a different context, it should be given a different underlying localization ID (key)**, so that it can be translated differently in the two contexts. (eg. if it occurs sometimes as a label on a stat profile and sometimes as a power-up toast in the HUD and sometimes as a column heading in a leaderboard, each of these may take different forms or need to be abbreviated differently to fit — something I ran into myself with gadget names in Splinter Cell Blacklist for example)

This includes if sometimes you want to display the word in a different case, or add a colon at the end like "Strength" vs "STRENGTH: 42" — different languages actually have different rules for how this is done, so it's better to let a translator pick the right way to do it for their language.

Each localization ID should be associated with not just the display text in the source language, but also with a **description explaining what it means in the context where it appears**. Then a translator can see both these pieces of information and take them into account when crafting an appropriate translation.

And lastly: you should **hire a proper translator**, a human with the judgement to navigate this context and the expertise to tell good translations from bad, something an automated online tool cannot do for you.

(Also, do not use my translations either — it's been a long time since I studied in French immersion, and so these examples themselves may be inaccurate, or technically valid but inappropriate for regional dialects)

---

I'd also add: localization is NOT the most boring part of game development. It's laborious, to be sure. But the challenge of identifying all the texts that need translation, organizing them in a way that's intuitive to work with, describing them in a way that's clear to translators, finding ways to assemble dynamic texts with proper gender and numeric agreement, and staying within display length budgets — it's *fascinating*.

If it's just a stepping stone on your way to your goal, then as Ze Frank says, try to fall in love with the shape of the stone.

(Or hire someone who will — you'll get better localization from someone who's passionate about it than someone who just wants to get it over with!)

---
Tags: localization
---


# Question
Title: Help on calculating distance between player position and other object collider end
So, imagine the drawing in 3d and obstacle is in front of the player, and I do a raycast for checking in front of the player and if the raycast hits the obstacle the player needs to check both left and right and move corresponding to the space it has on the x-axis and if the player has more space on the right then left he moves right and vice versa and the player has the bounds from A-B and the A-B is a Road and the road has mesh collider Please help me. I don't know how to check the space that the player has.

# Answer
> 1 votes
*Edit* -- revised to reflect new details from OP

I guess you are looking for something like this:

To calculate the distance to another collider, `Physics.Raycast` is sufficient.

Here's an example loosely based on code from your original post with cruft removed that isn't related to the task at hand. Assuming we know the width of the road, we can simply cast rays downward at half road width to the right and left of our position. Whichever hits is the side with the most room!

```
using UnityEngine;
public class CycleController : MonoBehaviour
{

    [SerializeField] private float checkDistance;
    [SerializeField] private float roadWidth;
    [SerializeField] private float moveSpeed;
    [SerializeField] private string obstacleLayer;
    [SerializeField] private string roadLayer;

    Rigidbody rb;
    public int obstacleLayerMask, roadLayerMask;
    Ray rayObstacle, rayRoadLeft, rayRoadRight;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        obstacleLayerMask = LayerMask.GetMask(obstacleLayer);
        roadLayerMask = LayerMask.GetMask(roadLayer);
    }

    private void Update()
    {
        //note calculating this every frame only for demo purposes...
        rayObstacle.direction = transform.forward;
        rayObstacle.origin = transform.position;
        rayRoadRight.direction = rayRoadLeft.direction = -transform.up;
        rayRoadRight.origin = transform.position + (transform.right * (roadWidth / 2f));
        rayRoadLeft.origin = transform.position - (transform.right * (roadWidth / 2f));

        Move();
        AIMove();
    }
    private void Move()
    {
        float verticalInput = Input.GetAxis("Vertical") * moveSpeed;
        rb.AddRelativeForce(0, 0, verticalInput, ForceMode.Force);
    }

    private void AIMove()
    {
        RaycastHit hitInfo;
       if(Physics.Raycast(rayObstacle, out hitInfo, checkDistance, obstacleLayerMask))
        {
            Debug.LogFormat("There is an obstacle named {0} {1:N2} units in front", hitInfo.collider.name, hitInfo.distance);

            if (Physics.Raycast(rayRoadLeft, out hitInfo, 10, roadLayerMask))
            {
                Debug.Log("there's room on the left!");
            }
            else
            {
                Debug.Log("there's no room on the left!");
            }

            if (Physics.Raycast(rayRoadRight, out hitInfo, 10, roadLayerMask))
            {
                Debug.Log("there's room on the right!");
            }
            else
            {
                Debug.Log("there's no room on the right!");
            }
        }
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green; // green ray checks for obstacles
        Gizmos.DrawRay(transform.position, rayObstacle.direction * checkDistance);

        Gizmos.color = Color.red; // red ray checks for road below
        Gizmos.DrawRay(rayRoadLeft.origin, rayRoadLeft.direction * 10);
        Gizmos.DrawRay(rayRoadRight.origin, rayRoadRight.direction * 10);
    }
}

```

First up, we're creating some layer masks so our Raycasts will only return hits on the objects we care about. `LayerMask.GetMask` does the bit twiddling for us. In `Update` I'm updating the rays for forward (obstacle collision) and downward left and right, largely because we are also using these rays to draw representations in `OnDrawGizmosSelected`. In OnAIMove we cast the obstacle ray out to the distance we care about. If it hits something it'll return true, and the passed `RaycastHit` *hitInfo* will be filled with useful information about what we hit, including how far away it is. At this point we'll cast two rays downward, to the left and right of our position. Since these distances are half the width of the road, only one cast will succeed if we are to the left or right already. (I'll leave it up to you to decide what to do if the player is exactly in the middle).

Here's the scene in play mode. green ray is for obstacle detection, red rays are for road detection.  The game view.  Console output.  The player config in the inspector. Layer mask ints are only exposed as public for debugging; these are computed by LayerMask.GetMask as related above.  This is the scene hierarchy.

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


title: Sprite won't flip properly

text:
# Question
Title: Sprite won't flip properly
I have a waypoint script I use to control enemy patrol movement in a given area. I use a reference to the Sprite Renderer to change the sprite facing direction. It starts with flipX set to false, by default, then is supposed to flip the sprite to the right direction, based on which trigger collider it detects. I have attached flipped if and else if statement below.

```
private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.gameObject.CompareTag("Waypoint2"))
    {
        sr.flipX = true;
    }
    else if (collision.gameObject.CompareTag("Waypoint"))
    {
        sr.flipX = false;
    }
}

```

However, when I press play to playtest, the sprite starts in the correct direction (walking toward Waypoint 1) but does not flip to face WP2. It then walks backward to WP2, and flips, which then causes him to walk backward toward WP1. I have switched the sr.flipX values to the opposite of what they are now, and have even moved the waypoints in the actual world.

Below is code showing waypoint index to create custom waypoints for each individual entity to have its own set.

```
[SerializeField] private GameObject[] waypoints;
private int currentWaypointIndex = 0;

```

# Answer
Well, since you asked for advice, I'm going to suggest this whole method of hardcoding the flip direction based on the gameObject's tag isn't going to be very easy or fun to maintain over time as you add/ move around waypoints, etc.

Instead, I suggest you simply calculate whether the next waypoint is in front or behind the sprite using the dot product and flip accordingly.

## DEMO

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

[RequireComponent(typeof(Sprite))]
public class WaypointMarch : MonoBehaviour
{
    [SerializeField] Transform[] waypoints;
    [SerializeField] AnimationCurve curve; // one way of moving our character around
    public int currentWaypointIdx; //exposed for debugging
    public Transform oldWayPoint, nextWayPoint;
    float timer;
    SpriteRenderer sprite;

    void Start()
    {
        sprite = GetComponent<SpriteRenderer>();
        oldWayPoint = waypoints[1];
        nextWayPoint = waypoints[0];
        currentWaypointIdx = 1;
    }

    void Update()
    {
        timer += Time.deltaTime;
        transform.position = Vector3.Lerp(oldWayPoint.position, nextWayPoint.position, curve.Evaluate(timer));
        if (timer >= 1.0f)
        {
            UpdateWaypoints();
        }
    }

    void UpdateWaypoints()
    {
        currentWaypointIdx = currentWaypointIdx >= waypoints.Length - 1 ? 0 : currentWaypointIdx + 1;
        oldWayPoint = nextWayPoint;
        nextWayPoint = waypoints[currentWaypointIdx];
        if (Vector3.Dot(-transform.right, transform.position - nextWayPoint.position) < 0)
        {
            Debug.Log("behind");
            sprite.flipX = true;
        }
        else
        {
            Debug.Log("ahead");
            sprite.flipX = false;
        }
        timer = 0;
    }
}

```

Code should be pretty straightforward to follow; to move the sprite from one WP to another I'm using an animation curve; when the sprite reaches the target waypoint (timer = 1) we increment or rollover the waypoint index; old WP becomes the current next WP and next WP is the next one in the array. We check to see if the next WP is ahead of us (to the right, in this case) and flip the sprite accordingly.

Scene Hierarchy:

Character Settings:
> 1 votes

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


# Question
Title: How do I pause/play animation in Unity without the animation getting cut off
I'm trying to achieve a common game behavior that when you hit an enemy, then whatever the enemy's action (animation) is, when the hit happens, the enemy pauses a bit, then continues with the animation. So everytime you hit the enemy, the enemy pauses for a bit.

I currently have this code:

```
IEnumerator StopStartMotion()
{
    _animator.speed = 0;
    yield return new WaitForSeconds(.2f);
    _animator.speed = 1;
}

```

Problem is, sometimes, when I hit too early in the enemy's animation (like at the beginning of a punch), the enemy pauses, and then doesn't continue the animation where he paused for a bit. Is there a better way of doing this?

I tried animator.enabled as well, but the animation also jumps.

# Answer
This is my solution for my game.

I disable the *Animator* so that the enemy stays in that frame. After I'm done, I re-enable the *Animator* and the enemy animation continues.

```
IEnumerator StopStartMotion()
{
    _animator.enabled = false;
    //DO SOMETHING HERE
    yield return new WaitForSeconds(.2f);
    _animator.enabled = true;
}

```
> 1 votes

---
Tags: unity
---


# Question
Title: What could be causing my texture in ash Vulkan to render lighter?
I have just completed the Vulkan tutorial using rust and the ash crate. I've been following along with this repository. I am unable to determine what is causing my textures to render lighter. If anyone can enlighten me as to any probable causes for this that would help a great deal.

My shaders are very basic. They are the exact same as what's in the tutorial, so I've ruled them out. I originally thought my problem had to do with multisampling but I've just completed that part of the course with no improvements to the color of my textures.

The texture I'm rendering from is directly taken from the vulkan-tutorial website. It looks as follows~

As you can see my render is clearly lighter. You'll see I am using the "image.rs" crate to get raw byte data to create the texture.

```
pub fn create_texture_image(
    device: &ash::Device,
    command_pool: vk::CommandPool,
    submit_queue: vk::Queue,
    device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
    image_path: &std::path::Path
) -> (vk::Image, vk::DeviceMemory, u32) {

    //Get image data
    let mut image_object = image::open(image_path).unwrap();
    image_object = image_object.flipv(); // flip vertically

    // destructuring image data
    let (image_width, image_height) = (image_object.width(), image_object.height());
    let image_size =
        (std::mem::size_of::<u8>() as u32 * image_width * image_height * 4) as vk::DeviceSize;

    let mip_levels = ((std::cmp::max(image_width, image_height) as f32)
        .log2()
        .floor() as u32)
        + 1;

    let image_data;
    image_data = match &image_object {
        image::DynamicImage::ImageLuma8(_) |
        image::DynamicImage::ImageBgr8(_) |
        image::DynamicImage::ImageRgb8(_) => image_object.to_rgba8().into_raw(),
        image::DynamicImage::ImageLumaA8(_) |
        image::DynamicImage::ImageBgra8(_) |
        image::DynamicImage::ImageRgba8(_) => image_object.to_rgba8().into_raw(),
        _ => { panic!("Image is not one of the 8 bit formats")}
    };

    if image_size <= 0 {
        panic!("Failed to load texture image");
    }

    let (staging_buffer, staging_buffer_memory) = buffer::create_buffer(
        &device,
        image_size,
        vk::BufferUsageFlags::TRANSFER_SRC,
        vk::MemoryPropertyFlags::HOST_VISIBLE |
        vk::MemoryPropertyFlags::HOST_COHERENT,
        device_memory_properties,
    );

    unsafe {
        let data_ptr = device
            .map_memory(
                staging_buffer_memory,
                0,
                image_size,
                vk::MemoryMapFlags::empty(),
            ).expect("Failed to Map Memory") as *mut u8;

        data_ptr.copy_from_nonoverlapping(image_data.as_ptr(), image_data.len());
        device.unmap_memory(staging_buffer_memory);
    }

    let (texture_image, texture_image_memory) = image_view::create_image(
        &device,
        image_width,
        image_height,
        mip_levels,
        vk::SampleCountFlags::TYPE_1,
        vk::Format::R8G8B8A8_UNORM,
        vk::ImageTiling::OPTIMAL,
        vk::ImageUsageFlags::TRANSFER_SRC
            | vk::ImageUsageFlags::TRANSFER_DST
            | vk::ImageUsageFlags::SAMPLED,
        vk::MemoryPropertyFlags::DEVICE_LOCAL,
        device_memory_properties,
    );

    transiiton_image_layout(
        device,
        command_pool,
        submit_queue,
        texture_image,
        vk::Format::R8G8B8A8_UNORM,
        vk::ImageLayout::UNDEFINED,
        vk::ImageLayout::TRANSFER_DST_OPTIMAL,
        mip_levels,
    );

    copy_buffer_to_image(
        device,
        command_pool,
        submit_queue,
        staging_buffer,
        texture_image,
        image_width,
        image_height,
    );

    generate_mipmaps(
        device,
        command_pool,
        submit_queue,
        texture_image,
        image_width,
        image_height,
        mip_levels,
    );

    unsafe {
        device.destroy_buffer(staging_buffer, None);
        device.free_memory(staging_buffer_memory, None);
    }

    (texture_image, texture_image_memory, mip_levels)
}

```

# Answer
> 2 votes
Special thanks to a comment by DMGregory! The issue is caused because my Texture ImageView and my texture were using different formats. One was set to R8G8B8A\_UNORM, and the other to R8G8B8A\_SRGB.

Resolved by setting the format of both to R8G8B8A8\_SRGB.

---
Tags: textures, vulkan, rust
---


# Question
Title: Calculating child world translation, rotation and scale
I'd like to know if it's possible to calculate a child's world translation, rotation and scale individually. I'm used to seeing devs resorting to matrix multiplication and then decomposition, like so:

```
// In the child's scene component
glm::mat4 const& childWorldMatrix = m_parent->GetWorldMatrix() * m_localTransform.GetMatrix();
glm::decompose(childWorldMatrix, worldScale, worldRotation, worldTranslation, skew, perspective);

```

But I was wondering if we could do it individually to avoid decomposition. This is my code but it's not correct, especially the rotation part which I believe to be "scaled".

```
glm::mat4 const& parentWorldMatrix = m_parent->GetWorldMatrix();
m_worldTransform.SetTranslation(parentWorldMatrix * glm::vec4(m_localTransform.GetTranslation(), 1.0f));
m_worldTransform.SetRotation(glm::toQuat(parentWorldMatrix * glm::toMat4(m_localTransform.GetRotation())));
m_worldTransform.SetScale(parentWorldMatrix * glm::vec4(m_localTransform.GetScale(), 1.0f));

```

The translation and scale getters/setters return/set a `glm::vec3` while the rotation uses `glm::quat`.

What would be correct way to calculate the world components individually?
Is matrix decomposition the preferred approach?

PS: I do have access to the individual components of the parent's world transform (world translation, world rotation and world scale), not just the matrix.

# Answer
> 0 votes
What you are doing here looks wrong to me, even just from the fact that the `.SetTranslation` and `.SetScale` are both essentially the same operation (you multiply the `parentWorldMatrix` to a `vec4` for both when they are very distinct things).

In order to do what you want, I think you'd have to take each component of the `m_localTransform` and handle it appropriately using the `m_parent`'s corresponding transform components with an exception for *Translation*.

```
m_wordTransform.SetRotation(glm::toQuat(parentWorldTransform.GetRotation() * m_localTransform.GetRotation()));
m_wordTransform.SetScale(glm::vec4(parentWorldTransform.GetScale() * m_localTransform.GetScale(), 1.0f));
m_wordTransform.SetTranslation(parentWorldTransform.GetTranslation() * parentWorldTransform.GetRotation() * parentWorldTransform.GetScale() * m_localTransform.GetTranslation());

```

Note: I think the glm code is not proper, some parts should be converted to vectors and others to whole matrices, not sure what the getters are returning.

The first two are simple to understand, the child component's world scale will be its own scale multiplied by the parent's scale. Same with rotation, multiplying the two rotation matrices generates the combined matrix that contains the local rotation of the child which is then further rotated by the parent rotation value. The trick here is with the translation of the child. Translation is actually affected by the other transformations, both rotation and scale. This is explained in linear algebra textbooks, if you want me to go further I can.

The point is that if you have a translation of \\$y=1\\$ and you apply a scale transform onto it, now your new \\$y\\$ position will be \\$y=2\\$ which means that the object has "moved" just because it was rescaled. For this reason, to properly generate the translation part of the `worldMatrix` you need to multiply the local translation with all of the parent's components and specifically in the order \\$TranslateRotateScale\\$ or \\$TRS\\$ for short, if you are multiplying from the left (i.e. applying scale first then rotation then finally the parent's own translation). You must **not** multiply the local translation vector with the whole parent transform! This generates wrong values.

---
Tags: mathematics, transformation, linear-algebra, glm, scene-graph
---


# Question
Title: How to recreate a comic book panel transition with my canvas (simple 2D background art)?
https://www.youtube.com/watch?v=Tqqf5Y8LyR8&t=23s&ab\_channel=ErikLoyer

So I want to achieve a transition like from the above video, specifically at 0:23 the TRACK, but there is a 3 Dimensional perspective to it. PUSH seems like the one I am talking about, but lets say the image(i.e panel in the video) gets pushed off camera and gets destroyed. How can I achieve this in Unity 2d?

# Answer
> 1 votes
There are at least three ways to achieve this, which one you choose depends on the particulars of your project.

# Script

You can animate your UI elements by manipulating the values of their `RectTransform` components during `Update` or a coroutine. The `AnimationCurve` class makes it quite easy to create ease-in and ease-out or bouncy effects.

# Animation Clips

You could author animation clips for your canvas elements that then are triggered by some user action (a "next" button, perhaps?)

# Timeline

The Unity Timeline is similar to creating individual animation clips but is more global in nature. This approach might make a lot of sense if there is only ever one way to move through the content.

# or some combination

All these methods can be combined, mixed and matched.

---
Tags: unity, 2d, gui, unity-ui
---


# Question
Title: How do I carve rooms and corridors into my map to connect exits placed at the edges?
I'm creating an adventure/RPG top down game where the map is randomly generated divided into zones. A major problem I'm having trouble figuring out is creating exits placed at the edges. The game is programmed in C.

My inspiration is the Windows game Indiana Jones and His Desktop Adventures:

The map here is composed of an 2D array containing smaller maps called zones. Each zone is connected to surrounding zones so when the player goes to the edge of the zone they will move to another zone.

My current solution is to use variables on each individual zone that are "links", but it may be too tedious to define each link for each zone. I'd like to find a better way than that.

I initialize the links like this (the numbers are the zone number) and they are connected:

```
zone[0].link_up = 2;
zone[1].link_down = 1;
zone[1].link_left = 6;
zone[5].link_right = 2;

```

An example of exiting around the edges:

```
if (player.x > zone[current_zone].map.width-1)
        {
                exit = zone[current_zone].link_right;
                if (exit)
                {
                        if (exitmaplink(exit, 1))
                                return;
                }
                player.x = zone[current_zone].map.width-1;
        }

```

# Answer
I've found a solution to the problem, I've made a structure called a zone which is a collection of maps.
> 0 votes

---
Tags: 2d, procedural-generation, tiles, maps
---


# Question
Title: Sometimes can't use the rendered mesh as a collider in Unity?
Most of the times I can use the `Mesh Filter`'s mesh as collider in `Mesh Collider`

But sometimes there is just nothing. No collider. Why?

I used this free asset: https://assetstore.unity.com/packages/3d/environments/fantasy/green-forest-22762

# Answer
> 1 votes
The documentation says that when the object has a rigidbody, then the mesh assigned to the mesh collider must be convex. Your screenshot doesn't show whether or not there is a rigidbody on the object. But the mesh of this tree looks anything but convex and the convex checkbox on the mesh collider isn't set.

But when trees in your game don't move (as is the usual behavior of trees), you can mark your trees as "static" by marking the "Static" checkbox in the upper right corner of the inspector (unfortunately also not shown on the screenshot). They then no longer need a rigidbody themselves in order to block other rigidbodies and they can now have a non-convex mesh collider.

However, you should still consider to create simpler meshes for collision purposes. Having a large number of mesh colliders with a high number of polygons in the scene can be a real performance killer. And players rarely notice it when collision meshes are far less detailed than the meshes used for rendering. With trees it is in fact usually expected that the small branches and leaves aren't solid. Common practice for trees is to create colliders which only approximate the trunk and the largest branches.

# Answer
> 0 votes
Sometimes setting to convex by itself doesn't work (it didn't for me). In that case try setting to convex and then setting the cooking option "inflate convex mesh"

---
Tags: unity, 3d-meshes, mesh, meshcollider
---


# Question
Title: How can I make explosions sound more harmonious?
I'm working on a game\* which has lots of explosions.

Audio feedback is important. If the explosion is large, or nearby, the player may want to take immediate action. I want a scaling audio cue for explosions.

The problem is the almost continuous explosion sound makes an uncomfortable white-noise background which is just unpleasant to listen to. I can't imagine wanting to play this for more than a few minutes without turning the sound off.

I've tried turning the explosion volume right down, but there doesn't seem to be a good compromise between making it comfortable and getting the cues. I've also tried replacing the explosions with samples from a drum kit. That sort of works, but the initial impression is poor ('why does it sound like a child playing on a drum machine?')

What technique(s) can be used to make explosions easier on the ears?

---

\*A 64 player bomberman clone, if it matters

# Answer
> 9 votes
A sound designer once showed me an interesting psychological phenomenon about synchronizing foley for footsteps (which I'm sure has a name that unfortunately I've forgotten).

They said that if you have 1-3 people walking on screen and you can see their feet, the footstep sounds have to match exactly. But if there are more feet than that, you can just play an almost random assortment of footfalls with no specific sync and the brain won't really complain.

There's kind of a threshold of complexity where our brain checks out and says "sure, I'll buy it".

So you may be able to take advantage of this.

Keep a separate channel around for bombs in the player's immediate vicinity, or bombs the player themselves placed. Those should always get unique sounds matched to them.

For all other bombs, not only can you attenuate them by distance, you can start to chunk them down by how many have gone off recently. Say the first and second "other" bomb to go off in the past 1 second interval get bespoke sounds each. But if a third bomb goes off within a second of two others, don't play a full explosion just for it. Instead, blend in a background rumble track representing "ambient explosions".

You can scale the loudness of that ambient track (or blend between different versions of it) based on how many "other" bombs have detonated in the recent time window, and fade it out entirely once that number drops down below 3 (or whatever threshold you choose).

If that same footstep foley trick applies, the brain should see a lot of explosions on screen, hear a lot of explosions in the track, and say "sure, I'll buy it," without attending to whether it can pair up every single on-screen flash to a specific boom.

This lets you cap the complexity of the soundscape to the ambient layer plus `n` individual booms, where you can tune `n` to your liking. You can also custom-design that ambient track (or its various layers/versions) so it sounds more pleasant than a lot of the same explosion sound repeating, and doesn't distract from the nearby bombs the player needs to focus on. (Though not being a sound designer myself, I can't detail exactly how you would do that).

That may not be a complete solution, but it's a strategy you can try to get a bit more granular control over the soundscape, and help you prioritize the most important sounds for the player to attend to.

---
Tags: game-design, sound
---


# Question
Title: How do I apply tiling and offset to a gameobject instead of material?
I would like to apply a texture to a plane. I want to assign a certain offset and tiling to it.

The material has a Tiling and Offset option. However, I don't want to do it on the Material level.

Why? The material has 5 different Tiling / Offset options. To try out different tiling / offsets, I have to change all 5 of them. This does not seem like a good workflow to me.

Instead, I would to apply the tiling / offset on the game object.

Is that possible?

Edit: I think what I actually need is a possiblity to change the UV of a mesh in a flexible way. I think I have found it in ProBuilder's UV options.

# Answer
> 2 votes
Just write a script that iterates over the material's texture properties and updates their tiling and scaling to match a master value.

```
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class MaterialScaler : MonoBehaviour
{
#if UNITY_EDITOR
    public Vector2 tiling = new Vector2(1, 1);
    public Vector2 offset = new Vector2(0, 0);

    private void OnValidate() {
        var properties = new List<int>();
        foreach(var material in GetComponent<Renderer>().sharedMaterials) {
            material.GetTexturePropertyNameIDs(properties);
            EditorUtility.SetDirty(material);

            Undo.RecordObject(material, "Change Shared Tiling/Offset");

            foreach(var id in properties) {
                material.SetTextureScale(id, tiling);
                material.SetTextureOffset(id, offset);
            }
        }
        AssetDatabase.SaveAssets();
    }
#endif
}

```

If you really want to pretend this is part of the responsibilities of the GameObject class itself, you could always write it as an extension method:

```
public static class GameObjectExtensions {
    public static void TransformAllTextures(this GameObject gameObject, Vector2 tiling, Vector2 offset) {
        var properties = new List<int>();
        foreach(var material in gameObject.GetComponent<Renderer>().sharedMaterials) {
            material.GetTexturePropertyNameIDs(properties);

            foreach(var id in properties) {
                material.SetTextureScale(id, tiling);
                material.SetTextureOffset(id, offset);
            }
        }
    }
}

```

You can now call this with:

```
someGameObject.TransformAllTextures(tiling, offset);

```

---
Tags: unity
---


title: How to copy a scene in Unity?

text:
# Question
Title: How to copy a scene in Unity?
When I use `CMD`+`D` on the current scene to duplicate and then I open the new scene,

I get this error message:

```
The following open scene(s) have been changed on disk:
 Assets/Level3.unity

Do you want to reload the scene(s)?

```

whatever I press leads me to a blank new scene

How can I copy everything from one scene to another?

# Answer
> 2 votes
It sounds like you might not have saved your changes to the current scene before duplicating it. Hit `File -> Save` first, to ensure your latest changes are saved to the scene file on disc before duplicating that file.

As an alternative, you can open the scene you want to clone, then go to `File -> Save As...` and save it under a new name. That will save all the contents of the current scene into a new scene file, giving you a second copy of the scene.

---
Tags: unity, scene
---


# Question
Title: How do I make an object bounce off the wall?
I am spawning objects at a random place at the top of the screen, tilted at a random angle like this:

```
[SerializeField] Vector2 spawnSizeMinMax;
[SerializeField] float spawnAngleMax;

void Update()
{
    if (Time.time > nextSpawnTime)
    {
        nextSpawnTime = Time.time + SecondBtwnSpawns;

        float spawnAngle = Random.Range(-spawnAngleMax, spawnAngleMax);  //rotation
        float spawnSize = Random.Range(spawnSizeMinMax.x, spawnSizeMinMax.y);  //Size
        Vector2 SpawnPos = new Vector2(Random.Range(-SpawnX, SpawnX), 5.67f);  //position for their spawn
        GameObject newBlock = (GameObject)Instantiate(fallingRock, SpawnPos, Quaternion.Euler(Vector3.forward * spawnAngle));
        newBlock.transform.localScale = Vector2.one * spawnSize;
    }
}

```

And then I use this script to move them down along their local "down" vector (which may be pointing along a diagonal), and reflect them off of the walls when they hit:

```
[SerializeField] float DropSpeed = 10f;
Rigidbody2D rb;
Vector3 lastVelocity;

void Awake()
{
    rb = GetComponent<Rigidbody2D>();
}

void Update()
{
    lastVelocity = rb.velocity;
    DropDown();
}

void DropDown()
{
    transform.Translate(Vector3.down * DropSpeed * Time.deltaTime);
}

void OnCollisionEnter2D(Collision2D collision)
{
    var speed = lastVelocity.magnitude;
    var direction = Vector3.Reflect(lastVelocity.normalized, collision.contacts[0].normal);

    rb.velocity = direction * Mathf.Max(speed, 2f);
}

```

But when I use this code, they don't bounce off the wall. How can I fix that?

# Answer
You should not mix `Transform` changes (like `transform.Translate()`) with `Rigidbody`/`Rigidbody2D` movement. Use one or the other exclusively. If you want your object to move with physics, let the physics engine handle *all* its movement.

Mixing these means anytime you edit the `Transform`, you're ripping the object out of the control of the physics engine, teleporting it, then throwing it back in haphazardly. This can result in inaccurate collision resolution (because there's a component to the object's motion that's invisible to the physics engine which only sees its `velocity`), performance issues (the physics engine has to do extra work every time you teleport the object), and confusing trigger/collision messages (every time the object teleports, you get a fresh pair of enter/exit events).

In this instance, because the diagonal falling is coming from the transform, not the body's velocity, it has no velocity to reflect!

I think you want something more like this:

```
public class Bouncer : MonoBehaviour {
    [SerializeField] float DropSpeed = 10f;
    Rigidbody2D rb;
    Vector2 lastVelocity;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();

        // Apply your initial velocity on spawn.
        // Then you don't need to transform the object every update tick.
        rb.velocity = transform.up * -DropSpeed;
    }

    // Do this in FixedUpdate, so you're caching the velocity in every
    // physics step, rather than only on rendered frames.
    void FixedUpdate()
    {
        lastVelocity = rb.velocity;
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        var speed = lastVelocity.magnitude;
        var direction = Vector2.Reflect(lastVelocity.normalized,
                                        collision.contacts[0].normal);

        rb.velocity = direction * Mathf.Max(speed, 2f);
    }
}

```

I've tested this and it correctly bounces an object off a wall with the same speed it had coming in. Though you get pretty much the same behaviour without this script at all, just using a `PhysicsMaterial2D` with `Friction = 0` and `Bounciness = 1` and giving your `Rigidbody2D` an initial velocity or impulse to start it off.
> 1 votes

---
Tags: unity, c#, 2d, physics
---


# Question
Title: How to do State-Based Animation with ECS
I'm making a simple platformer game and was suggested to use ECS from a friend. It looked pretty interested and at least worth a try, so I did. I got ECS working and started work on the rendering system. But I have no idea how to do it, at least correctly, given that each enemy type will have multiple animation sequences that it'll switch to depending on what its doing. A zombie might have a walk, idle, and attack sequences, while a bat would only have the fly animation. This question also extends to AI systems, but rendering is the priority right now.

The way I see it there are 2 possible ways, but neither seem like the right way.

1. create a different component and system for every type, like ZombieSpriteComponent, ZombieSpriteRenderSystem, BatSpriteComponent, BatSpriteRenderSystem, etc.
2. shove all the states from the individual types into a giant component and system which switches depending on whether the given component has the state. hasWalkState, hasAttackState, hasFlyState, etc.

I'm using C++, SDL, and a custom ECS I wrote based on this, in case it helps.

# Answer
I'd recommend taking a look at how this is handled in other component-based engines (not necessarily full ECS). That will give you some examples of how to attack this problem with reusable components, in a way that you know has successfully shipped other games.

Taking Unity for example, they separate out a reusable Animator component (/system) that just generically plays animation state machines provided to it as data.

The state machine (called an Animator Control Graph) is a collection of Animation Clips (timelines of keyframes & interpolation curves) which serve as nodes/states in the graph, and transitions which describe when to switch/blend between two clips, basically directed edges between nodes. It can also contain a list of properties to use in conditions that enable/disable various transitions or modulate the playback and blending.

An instance of this graph will have variables to keep track of the current state / transition, the playhead position in any playing clips, and something like a map containing the current values of its properties.

This helps decouple the visual/animated representation of a state from the player control / AI behaviour that triggers those states.

A movement component might get a reference to its Animator and send it data like:

* `SetFloat("horizontalSpeed", velocity.x)`
* `SetBool("isGrounded", groundRaycast.hit)`

...and the decision about how to translate those properties to animations lives completely in the data of the graph being navigated by a general-purpose animation system, rather than needing one-off code.

I could use the same movement and animation components/systems and their underlying code for a character that walks and a character that slithers, just by putting walking keyframe sequences into one graph and slithering keyframe sequences into the other, but using the same vocabulary of property keys to drive both state machines.

This pattern of "put the differences in data" repeats for the AI behaviour side of the equation too. I could make a movement component take parameters that describe its movement speed and acceleration to get many different movement behaviours out of one set of code. For their AI brains, I could use a reusable BehaviourTree component, and feed it different trees of behaviour states as data.

But to get the difference between flying enemies like bats and ground-based enemies like zombies, you'd probably want different code. To avoid creating new components/systems for every single object type, try to focus on composition: build up a complex behaviour out of reusable modular pieces.

Have a Ground Movement component and a Flying Movement component that can both expose a similar API to the brain logic in the behaviour component(s), and both communicate with the animation component. That way you can mix and match those components freely to get new behaviour combinations out of the same code (like a Vampire enemy that has both a FlyingMovement and GroundMovement, with only one enabled at a time as it switches between bat and humanoid forms...)

Overall, whenever you can, try to rephrase your problems from "is a" to "has a". It's not that a bat enemy "is a" bat. It "has a" flying animation, and a flying movement, etc. Those "has a" relationships clarify how you can represent the particular traits of a game entity with swappable data and reusable building blocks, rather than one-off code.
> 2 votes

---
Tags: animation, entity-component-system
---