# Question
Title: 2D Per Pixel Collision Detection using Animated Sprite
I am using **MonoGame 3.6** and **Visual Studio 2017**.

I have been trying to find a solution online to do per pixel collision detection using an animated sprite that I am drawing from a sprite sheet.

Using the following code which is not working:

The `BoundingRectangle` and `Position` on the `AnimatedSprite.cs`

```
public Vector2 Position
    {
        get { return position; }
        set
        {
            position = value;
        }
    }

public virtual Rectangle BoundingRectangle
    {
        get
        {
            return new Rectangle(
                (int)Position.X,
                (int)Position.Y,
                Width,
                Height);
        }

    }

public static bool CheckForPixelCollision(AnimatedSprite a, AnimatedSprite b)
    {
        // Get Color data of each Texture
        Color[] dataA = new Color[a.Width * a.Height];
        Color[] dataB = new Color[b.Width * b.Height];

        a.Texture.GetData(0, a.Animations[a.CurrentAnimation].CurrentFrameRect, dataA, 0, a.Width * a.Height);
        b.Texture.GetData(0, b.Animations[b.CurrentAnimation].CurrentFrameRect, dataB, 0, b.Width * b.Height);

        int top = Math.Max(a.BoundingRectangle.Top, b.BoundingRectangle.Top);
        int bottom = Math.Min(a.BoundingRectangle.Bottom, b.BoundingRectangle.Bottom);
        int right = Math.Max(a.BoundingRectangle.Right, b.BoundingRectangle.Right);
        int left = Math.Min(a.BoundingRectangle.Left, b.BoundingRectangle.Left);

        for (var y = top; y < bottom; y++)
        {
            for (var x = left; x < right; x++)
            {
                Color color1 = dataA[(x - a.BoundingRectangle.Left) + (y - a.BoundingRectangle.Top) * a.Width];
                Color color2 = dataB[(x - b.BoundingRectangle.Left) + (y - b.BoundingRectangle.Top) * b.Width];

                if (color1.A != 0 && color2.A != 0)
                    return true;
            }
        }

        return false;
    }

```

When I run this code, I get `OutOfRangeException` when it tries to get the color out of the array. I am trying to achieve the following steps:

1) Extract the colors from both `AnimatedSprites` from their `SpriteSheet` only for the current frame that is drawing from the `Animation`

2) Check if any of the pixels in the intersecting rectangle are not transparent and return a collision.

An example of how the code will be called when checking `Player` movement capabilities:

```
                var nextPosition = (Sprite.Position + (motion * PlayerSpeedAmplifier));
                var playerTempRectangle = new Rectangle((int)nextPosition.X, (int)nextPosition.Y, PlayerCurrentRectangle.Width, PlayerCurrentRectangle.Height);
foreach (var enemy in listOfEnemies)
                {
                    if (playerTempRectangle.Intersects(enemy.EnemyCurrentRectangle))
                    {
                        if (Helper.CheckForPixelCollision(Sprite, enemy.Sprite))
                        {
                            canMove = false;
                            break;
                        }
                    }
                }

```

I hope someone can please help. Let me know if you need any additional information.

# Answer
I know it's been quite a while but I thought I'd provide my working solution to this problem. I'm providing two methods that I used to test if two frames in a sprite sheet collide using per pixel collision detection. Call the one that takes the destination of sprite a, source rectangle of sprite a, the texture of sprite a, the destination of sprite b, the source rectangle of sprite b and the texture of sprite b. The comments should answer any questions as to what the code is doing.

        ///
        /// Checks if two sprites in a sprite sheet collide using per pixel collision detection
        ///
        /// <param name="destinationA">Desstination of sprite A</param>
        /// <param name="sourceA">Nullable source rectabgke of sprite A in the sprite sheet</param>
        /// <param name="textureA">Texture for sprite sheet A</param>
        /// <param name="destinationB">Destination of sprite B</param>
        /// <param name="sourceB">Nullable source rectangle of sprite B in the sprite sheet</param>
        /// <param name="textureB">Texture for sprite sheet B</param>
        /// <returns></returns>
        public static bool SpriteSheetCollision(
            Rectangle destinationA,
            Rectangle? sourceA,
            Texture2D textureA,
            Rectangle destinationB,
            Rectangle? sourceB,
            Texture2D textureB)
        {
            // If the sourceA is null use entire texture
            if (sourceA == null)
            {
                sourceA = new Rectangle(0, 0, textureA.Width, textureA.Height);
            }

            // Grab the texture data for checking if the pixels collide in the source rectangle
            Color[] textureDataA = new Color[sourceA.Value.Width * sourceA.Value.Height];
            textureA.GetData(0, sourceA, textureDataA, 0, textureDataA.Length);

            // If the sourceB is null use the entire texture as the source rectangle
            if (sourceB == null)
            {
                sourceB = new Rectangle(0, 0, textureB.Width, textureB.Height);
            }

            // Grab the texture data for checking if the pixels collide in the source rectangle
            Color[] textureDataB = new Color[sourceB.Value.Width * sourceB.Value.Height];
            textureB.GetData(0, sourceB, textureDataB, 0, textureDataB.Length);

            // Call the per pixel collision detection code
            return ColorDataCollides(destinationA, textureDataA, destinationB, textureDataB);
        }

        ///
        /// Checks to see if two areas of color data collide
        ///
        /// <param name="a">Destination rectangle of area A</param>
        /// <param name="textureDataA">Color data for area A</param>
        /// <param name="b">Destination rectangle of area B</param>
        /// <param name="textureDataB">Color data for area B</param>
        /// <returns></returns>
        public static bool ColorDataCollides(Rectangle a, Color[] textureDataA, Rectangle b, Color[] textureDataB)
        {
            // Find the bounds of the rectangle intersection
            int top = Math.Max(a.Top, b.Top);
            int bottom = Math.Min(a.Bottom, b.Bottom);
            int left = Math.Max(a.Left, b.Left);
            int right = Math.Min(a.Right, b.Right);

            // Check every point within the intersection bounds
            for (int y = top; y < bottom; y++)
            {
                for (int x = left; x < right; x++)
                {
                    // Get the color of both pixels at this point
                    Color colorA = textureDataA[(x - a.Left) +
                                            (y - a.Top) * a.Width];
                    Color colorB = textureDataB[(x - b.Left) +
                                            (y - b.Top) * b.Width];

                    // If both pixels are not completely transparent,
                    if (colorA.A > 0 && colorB.A > 0)
                    {
                        // then an intersection has been found
                        return true;
                    }
                }
            }

            // No intersection found
            return false;
        }
```

> 1 votes

# Answer
I found an algorithm that works for my scenario.

https://www.youtube.com/watch?v=YxYRj2njBxE
> 0 votes

---
Tags: c#, collision-detection, monogame
---


# Question
Title: How to make player walk through layers of 2d fog smoothly?
I'm trying to recreate the fog effect that Graveyard Keeper has, with several layers, so taller objects will get less fog. I'm using the approach described here: the devs post on Gamasutra

The problem with this approach is when the player is walking through each layer, it comes in front of the fog, and the fog effect "pops away", as the fog is thicker on the bottom of the fog layer. See the image where the fog is a little exaggerated.

I'm using Unity and all layers are in the "Default" sorting layer, and Y as the custom sort axis, so sprites higher up are behind lower sprites.

The jarring effect is worse the thicker fog I have.

How can I solve this, so the player doesn't "blink" like this? Thanks!

# Answer
> 0 votes
Because the OP stated that depth testing isn't a good option, I propose a simpler approach based on z-index alone, with tuned parameters to hide the "abrupt transition effect".

Render 0: yellowish solid color layer always on top

Render 1: removed the always on top layer (for comparison). The fog is neutral gray, the top layer changed the mood of the scene before, maybe too much.

Render 2: exaggerated fog intensity, no always on top layer (for comparison)

Some considerations:

If we impose ourselves no buffer access, no low level OpenGL/other APIs calls, no custom shaders, we are a bit limited in what we can do.

The asset used for the fog is provided to examine it. It can be improved, for example: borders must be softer. Suggestion: play with Blur effects and other filters.

The original fog assets came from here: https://opengameart.org/content/thick-fog

The original character assets came from here: https://opengameart.org/content/tmim-heroine-bleeds-game-art

The fog asset is 1024 pixels wide. For our fog, I took a rectangle of 1024x85, very close to the top of the original fog full image.

To avoid artifacts when two rows of fog intercept in the y axis, I used the Gimp lasso tool to round borders, including the bottom border, and then blur bottom and top borders.

While each fog row is 85 pixels in height, their are separate from each other by 20 pixels in the y axis. We want overlapping to have a better continuity effect, but borders must be taken care of with proper blurring, for example. Rough borders won't do. The ones here aren't perfect either and probably only useful for testing.

The rows move at different speeds. The speed table is:

```
var speed_table = [1, 0.5, 2, 0.25, 0.75, 1.25]

```

The loop that instantiates the rows cycle through that table, and if it reach the end it starts at the beginning again. This is needed because there are more fog rows than entries in the speed table.

Formula to determine how many rows we need:

```
rows = viewport_height / row_distance_y

```

The resulting fog row asset:

Because that image is nearly all transparent, this other version serves to appreciate it better:

But the first one is the one that must be used for experimentation.

All of these parameters, the height of the fog, the separation of 20 pixels, the alpha of the pixels, all must be played with until ideal ones are found. In the first render, for example, the top layer hides the fog rows too much, somewhat defeating its purpose.

---
Tags: unity, 2d, shaders, sprites, graphic-effects
---


# Question
Title: What is the Unity 2019.3.5 version of `UnityEngine.UI.Text`?
I was following a tutorial on how to create a dialogue Box in Unity, and in one part of the tutorial the tutor imports `UnityEngine.UI` and creates an object of type `Text`, but my version of Unity is 2019.3.5f1 and I learned through searching a bit online that this `UnityEngine.UI` doesn't exist anymore in this version, and that it was replaced with `UnityEngine.UIElements`, and this `Text` type doesn't exist anymore as well.

I couldn't find a replacement for `Text` or what is the new nomenclature, nothing from trying stuff that popped in the auto complete or searching for answers in the Internet gave me answers. Maybe I just searched poorly, but if anyone happens to know, could you kindly answer?

# Answer
> 2 votes
It's still the same.

`UnityEngine.UI` didn't go away, **it's just considered a package now,** so its documentation has moved out of the core and into its own sub-page.

Open your Package Manager window, and install/update the Unity UI package if it's not installed or out of date.

Now adding `using UnityEngine.UI;` at the top of your script will let you access the `Text` type just like in the tutorial.

(Though for many purposes you'd likely prefer the `TMPro.TextMeshProUGUI` type, which does the same thing but with signed distance field rendering that tends to look more crisp, and offers more powerful styling options. Add the TextMeshPro package to use this one.)

---
Tags: unity, gui, text, unity-ui
---


# Question
Title: How can I move the object back to his original position after the object reached the target?
```
InteractableItem target;
    private void Update()
    {
        if (target != null && target.name == "kid_from_space_helmet")
            objToThrow.transform.position += (target.transform.position - objToThrow.transform.position).normalized * 2f * Time.deltaTime;

        if(Vector3.Distance(objToThrow.transform.position, target.transform.position) < 1f)
        {
            objToThrow.transform.position += (objToThrow.transform.position - target.transform.position).normalized * 2f * Time.deltaTime;
        }
    }

```

The object is moving to the target but never moving back. This IF is not working good :

```
if(Vector3.Distance(objToThrow.transform.position, target.transform.position) < 1f)

```

My guess is that the problem is that when the object distance is less then 1 he try to move back but then he is not less then 1 anymore. but anyway it's not working.

I want to move the object to the target then wait 1 second at the target and then to move the object back.

# Answer
> 1 votes
The problem is that the if-statement will only be true while the object is close to the target. As soon as it moved far enough back to no longer be within 1.0 units, it returns to its old behavior of moving back to the target.

What you have here is an object which can be in two different **states**. The "moving to target" state and the "moving to origin" state. So you need to:

* Keep track of which state the object is currently in
* Change that state when the condition for state-change is fulfilled
* Make the object behave differently depending on which state it is currently in

As long as you only have two states, you can store the current state in a bool variable.

```
private bool isMovingBack = false; // the state the object is currently in

private void Update() {
    // check if the condition for state-change is fulfilled
    if(Vector3.Distance(objToThrow.transform.position, target.transform.position) < 1f) {
        isMovingBack = true;
    }

    // behave according to current state:
    if (isMovingBack == false) {
        objToThrow.transform.position += (target.transform.position - objToThrow.transform.position).normalized * 2f * Time.deltaTime;
    } else {
        objToThrow.transform.position += (objToThrow.transform.position - target.transform.position).normalized * 2f * Time.deltaTime;
    }
}

```

A boolean state is fine as long as the object can only be in one of two states. But when you start creating objects which can be in more than two states, then it might be worth it to look into finite state machines. One simple way to implement this in C# is to have a class-local enum for all the states the object can be in and then have a switch-statement in your Update-method which runs different code depending on the current state.

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


title: 2D/3D Soft body physics in Unity

text:
# Question
Title: 2D/3D Soft body physics in Unity
I want to implement soft bodies in my game similar to this link.

I tried using this Soft body simulation plugin but it has the following problems:

1. Only works with box colliders.
2. Doesn’t work with Unity’s physics engine i.e. the bodies don’t react to the forces applied.

For my game,

1. The soft bodies should be able to collide and interact with any types of colliders (including mesh collider).
2. The bodies should work with Unity’s physics engine i.e. the bodies should react to the forces and gravity applied.

I am flexible in implementing soft bodies in 2D or 3D.

I would appreciate any suggestions and thoughts on this topic.

# Answer
The 3D soft bodies can be implemented using spring joints and mesh bones. Assign spring joint to each bone and connect it to all the other bones.

Tutorial link: https://www.youtube.com/watch?v=tTdKEJpX2HI&feature=youtu.be&t=1088
> 1 votes

---
Tags: unity, 2d, physics, 3d, soft-body-dynamics
---


# Question
Title: I can't select my local package in Asset Store Tools
I made a local package and I'm trying to upload it to the AssetStore.
-My package is stored in the \[root\]/Packages folder.
-My Demo scene is stored in the \[root\]/Assets folder.

When I try to upload my package in the Asset Store Tools, I've an error if I select my sources in the Packages folder.
If i select my Demo scene folder instead, I have no error. But I don't want to upload only my Demo scene.
If I check 'include dependecies' it only add a json manifest file.

The error message is : *The path selected must be inside the currently active project.*

All answers about this error on google didn't helped me.
-Set the package as a Full project =\> I made a tool not a full project.
-The Project have to be in C:\ Hard drive =\> it is.
-The Project folder must have the package's name =\> it is. My project folder's name PropertyInterface as my asset.

I'm using Unity 2019.1.0f2.

It's the first time i try to upload my work in the Asset store. I'm pretty confused.

Thanks for your help.

# Answer
Sadly as @Troien said : It's not possible to upload your local or embedded package in the asset store as \[root\]/Packages folder content.

> Looking further into it, I did find a source that claims it is not possible at this time ;) – troien yesterday

To upload it, you need to store it in the \[root\]/Assets folder. I recommand to use \[root\]/Assets/Plugins/\[YourAssetName\] as hierarchy. If you do that you should delete your manifest and '.asmdef' files.
> 0 votes

---
Tags: unity, assets
---


# Question
Title: Why is my sine based scale animation not changing?
I followed the code at this YouTube channel: https://www.youtube.com/watch?v=OR0e-1UBEOU&t=4178s, and did some modification on the code so that the scale of the bird will change during projectile using the absolute sine function under the if statement.

I'm using the scale `(16/20)*|sin(distance)|` for my x and y component. However, when I launch the game, the scale stays as 0 along the path. Why is my scale staying as a constant zero?

```
using UnityEngine;
using UnityEngine.Assertions.Must;
using UnityEngine.SceneManagement;

public class Bird : MonoBehaviour
{
    Vector3 OldPosition;
    Vector3 DistanceDifference;
    float TotalDistance = 0;
    Vector3 _initialPosition;
    private bool _birdWasLaunched;
    [SerializeField] private float _launchPower = 500;

    void start()
    {
        OldPosition = transform.position;
    }

    private void Awake()
    {
        _initialPosition = transform.position;

    }

    void Update()
    {
        if (_birdWasLaunched && GetComponent<Rigidbody2D>().velocity.magnitude > 0.1)
        {
            DistanceDifference = transform.position - OldPosition;
            TotalDistance += DistanceDifference.magnitude;
            OldPosition = transform.position;
            transform.localScale = new Vector3((16/20)*Mathf.Abs(Mathf.Sin(TotalDistance/5)), (16/20)*Math.Abs(Mathf.Sin(TotalDistance /5)) , Mathf.Sin(TotalDistance /5));
        }

        if (transform.position.y > 15.00 || transform.position.y < -15.00 || transform.position.x > 18 || transform.position.x < -18)
        {
            string currentSceneName = SceneManager.GetActiveScene().name;
            SceneManager.LoadScene(currentSceneName);
        }
    }

    void OnMouseDown()
    {
        GetComponent<SpriteRenderer>().color = Color.red;
    }

    private void OnMouseUp()
    {
        GetComponent<SpriteRenderer>().color = Color.white;
        Vector2 directionToInitialPosition = _initialPosition - transform.position;
        GetComponent<Rigidbody2D>().AddForce(directionToInitialPosition * _launchPower);
        GetComponent<Rigidbody2D>().gravityScale = 1;
        _birdWasLaunched = true;
    }

    private void OnMouseDrag()
    {
        Vector3 newPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        transform.position = new Vector3(newPosition.x, newPosition.y);
    }
}

```

# Answer
> 3 votes
(16/20) is integer division, resulting in 0. Replace that with `0.8f` or `(16/20.0f)`.

---
Tags: unity
---


# Question
Title: What is the package-lock.json file for in Unity?
My project contains this file: Packages/packages-lock.json

And I'm curious about what it's for. It has a bunch of json about my packages in it, but it's not clear to me what goes in the lock file vrs the normal packages file.

# Answer
`Packages` contains two files. The `manifest.json` file stores all the *direct* dependencies for your Unity project. For example:

```
{
    "dependencies": {
        "com.unity.modules.animation": "1.0.0",
        "com.unity.modules.assetbundle": "1.0.0",
        "com.unity.modules.audio": "1.0.0",
        ...
    }

```

When Unity resolves these it also needs to download other packages. The other `packages-lock.json` file stores references to the specific versions of these *indirect* dependencies required to support your dependencies.

```
{
  "dependencies": {
    "com.unity.2d.animation": {
      "version": "4.2.6",
      "depth": 1,
      "source": "registry",
      "dependencies": {
        "com.unity.2d.common": "3.0.1",
        "com.unity.mathematics": "1.1.0",
        "com.unity.2d.sprite": "1.0.0",
        "com.unity.modules.animation": "1.0.0",
        "com.unity.modules.uielements": "1.0.0"
      },
      "url": "https://packages.unity.com"
    },

```

Since dependencies sometimes have their own dependencies, many of which are shared by other dependencies, the `packages-lock.json` file resembles less a list of packages, and more a dependency graph (note the `depth` field below of this package, which is used by `animation`, which is used by the project:

```
"com.unity.mathematics": {
  "version": "1.1.0",
  "depth": 2,
  "source": "registry",
  "dependencies": {},
  "url": "https://packages.unity.com"
},

```

The `packages-lock.json` also saves the specific versions of all indirect dependencies regardless if one of the dependencies is update later on. This ensures you and your collaborators all see the exact same project, all the way down to the smallest packages.

> The Package Manager can only install one package version at a time, so it has to construct a dependency graph in order to determine which version of each package to install. When the Package Manager successfully resolves all version conflicts, it saves the resolution in a lock file to ensure determinism (so that the same packages are reliably installed every time), and to reduce the amount of time and resources it takes to compute the dependency graph again.

So, to summarize. You need both and should commit both to source control.
> 2 votes

---
Tags: unity
---


# Question
Title: WEBGL antialias false to pixel art low resolution
I know this issue maybe repeated and seems to be very common but I searched first and did not find anything concrete.

I am doing some test and playing around with pixijs. I created an stage 320x180 and I am rendering an sprite of 27x27 in a autodetected renderer (WEBGL always is selected) I am in a macos retina resolution (devicepixerate 4) the problem is I can not achieve having the sprite pixelated even setting antialias false in the renderer. I tested the same without pixijs but native canvas 2d context using drawImage and I could get what I wanted using some hacks like after every drawImage set context.imagesmoothingenabled to false and I have CSS file to canvas image-rendering: pixelated. With those I am having exactly what I want, but of course I would like to obtain the same using pixijs and WEBGL. Is it possible? Disable at all antialias in a WEBGL context? How we can deal with this to render pixel arts properly?

**EDITED:** Using canvas 2d context native api

Using PixiJS webgl context.

Cheers.

# Answer
Helped me in html5gamedevs forum.

> **Solution**: The scale mode of the texture needs to be set to nearest. You can either do that on a texture by texture basis via the scaleMode property, or change the default via http://pixijs.download/dev/docs/PIXI.settings.html#.SCALE\_MODE Updated pixi from 4.5 tp 4.7, set scaleMode, set resolution:3 instead of css transform

Thread: http://www.html5gamedevs.com/topic/36463-pixijs-v4-does-not-remain-sprite-pixelated-as-it-original-is
> 3 votes

# Answer
Simple solutions using CSS:

```
canvas {
  image-rendering: pixelated;
}

```

The same can be applied to `img` tag or any other element with images on the background.

It allows you to render a 1-to-1 pixel scale, and resize your canvas into any resolution.
> 1 votes

---
Tags: html5, webgl, antialiasing
---


title: Calculate aim angle dead zone range

text:
# Question
Title: Calculate aim angle dead zone range
In my top down 2D shooter game the player has a shoulder mounted gun which rotates and aims automatically at enemies - that part is all working fine. Since the player can rotate as well, the gun is constantly updating it's angle to keep aim on the enemy.

But this causes a problem where the gun aims at the player's own head...! It doesn't have any practical consequences in the game, but obviously looks weird and unrealistic. So I need to create a 'dead zone' angle range where the gun cannot aim. It will have to aim as best it can at an enemy up to just before it aims at the player's head.

It seems tough to calculate since there are two angles in play. The dead zone will have to update itself as the player turns.

EDIT: This is what I had so far but I can't update the angle range since it then wouldn't work with the min max:

```
private float normaliseAngle(float angle) {
    return angle - (float) Math.floor(angle / 360f) * 360f;
}

private float clampAngle(float aimAngle) {
    float tempAngle = normaliseAngle(aimAngle);
    return (float) Math.min(Math.max(tempAngle, 45), 315);
}

```

This gives a dead zone between 315 and 45.

# Answer
> 1 votes
If you use a bounding circle for the player then the "*dead zone*" can be defined as whenever the line-of-sight ray from the gun to the target intersects with the circle.

Detecting that the gun is intersecting the player is simple, in **libGDX** the `Intersector.intersectSegmentCircle` method is useful for this.

What is harder is to rotate the gun so that it faces the target without ever rotating *over* the player.

One way of achieving this is to measure the *signed angle* between the vector from the gun to the target and from the gun to the center of the player.

```
Vector2 gunToTargetDirection = new Vector2(target).sub(gunPosition);
Vector2 gunToPlayerDirection = new Vector2(playerPosition).sub(gunPosition);
float gunToTargetAngle = signedAngleBetween(gunDirection, gunToTargetDirection);
float gunToPlayerAngle = signedAngleBetween(gunDirection, gunToPlayerDirection);

```

then you can compare the sign of those angles, and if they're the same and the angle to the player is smaller than the angle to the target then flip the sign of the rotation thus forcing the gun to rotate *the long way round*:

```
float gttaS = Math.signum(gunToTargetAngle);
float gtpaS = Math.signum(gunToPlayerAngle);
float direction;

if (gttaS == gtpaS) {
    if (Math.abs(gunToTargetAngle) < Math.abs(gunToPlayerAngle))
        direction = gttaS;
    else
        direction = -gttaS;
} else {
    direction = gttaS;
}

gunRotation += direction * maxGunTurnSpeed * Gdx.graphics.getDeltaTime();

```

An example of this might look like this **player** is green, **gun** is red and **target** is yellow. The line inside the player and the gun indicates the direction of these and the cyan line indicates that the gun has a clear line of sight to the target and will try to rotate the gun to point at it, without overlapping with the player. The gun is always mounted on the player's left shoulder.

In this example the gun goes passive when it cannot see the target and simply follows the player's rotation, but this could easily be changed to a more interesting behavior.

The full source code for the example above is:

```
package com.somepackage;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;

public class SomeCoolGameWithAShoulderCannonJustLikeInThePredator extends Game {
    OrthographicCamera camera;
    ShapeRenderer shapeRenderer;
    Vector2 playerPosition = new Vector2();
    Vector2 playerDirection = new Vector2(1.0f, 0.0f);
    float playerRotation = 0.0f;
    float playerSpeed = 0.0f;
    float playerSize = 32.0f;
    float gunRotation = 0.0f;
    float gunSize = 16.0f;
    Vector2 gunPosition = new Vector2();
    Vector2 gunDirection = new Vector2(1.0f, 0.0f);
    Vector2 target = new Vector2(100.0f, 0.0f);

    @Override
    public void create() {
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        shapeRenderer = new ShapeRenderer();
    }

    private void renderPlayer() {
        shapeRenderer.setColor(Color.GREEN);
        shapeRenderer.circle(playerPosition.x, playerPosition.y, playerSize, 16);
        shapeRenderer.line(playerPosition.x, playerPosition.y, playerPosition.x + playerDirection.x * playerSize, playerPosition.y + playerDirection.y * playerSize);
    }

    private void renderGun(boolean targetIsObscuredByPlayer) {
        if (!targetIsObscuredByPlayer) {
            shapeRenderer.setColor(Color.CYAN);
            shapeRenderer.line(gunPosition.x, gunPosition.y, target.x, target.y);
        }
        shapeRenderer.setColor(Color.RED);
        shapeRenderer.circle(gunPosition.x, gunPosition.y, gunSize, 16);
        shapeRenderer.line(gunPosition.x, gunPosition.y, gunPosition.x + gunDirection.x * gunSize, gunPosition.y + gunDirection.y * gunSize);
    }

    private void renderTarget() {
        float targetSize = 8.0f;
        shapeRenderer.setColor(Color.YELLOW);
        shapeRenderer.circle(target.x, target.y, targetSize, 16);
    }

    private float signedAngleBetween(Vector2 a, Vector2 b) {
        Vector2 na = (new Vector2(a)).nor();
        Vector2 nb = (new Vector2(b)).nor();
        return ((float) Math.atan2(nb.y, nb.x) - (float) Math.atan2(na.y, na.x)) * MathUtils.radiansToDegrees;
    }

    private float wrapAngle(float angle) {
        angle = angle % 360;
        if (angle < 0)
            angle += 360;
        return angle;
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0, 0, 0, 0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        float maxPlayerSpeed = 64.0f;
        float playerAcceleration = 8.0f;
        float maxPlayerTurnSpeed = 90.0f;
        float maxGunTurnSpeed = 120.0f;

        playerSpeed *= 0.95f;
        float playerDeltaRotation = 0.0f;

        if (Gdx.input.isKeyPressed(Input.Keys.W))
            playerSpeed = Math.min(maxPlayerSpeed, playerSpeed + Gdx.graphics.getDeltaTime() * playerAcceleration);
        if (Gdx.input.isKeyPressed(Input.Keys.S))
            playerSpeed = Math.max(-maxPlayerSpeed, playerSpeed - Gdx.graphics.getDeltaTime() * playerAcceleration);
        if (Gdx.input.isKeyPressed(Input.Keys.A))
            playerDeltaRotation += Gdx.graphics.getDeltaTime() * maxPlayerTurnSpeed;
        if (Gdx.input.isKeyPressed(Input.Keys.D))
            playerDeltaRotation -= Gdx.graphics.getDeltaTime() * maxPlayerTurnSpeed;

        playerRotation += playerDeltaRotation;
        playerRotation = wrapAngle(playerRotation);

        playerDirection.set(1.0f, 0.0f).rotate(playerRotation);
        playerPosition.x += playerDirection.x * playerSpeed;
        playerPosition.y += playerDirection.y * playerSpeed;

        gunPosition.set(playerDirection).scl(playerSize + gunSize).rotate(90).add(playerPosition);

        boolean targetIsObscuredByPlayer = true;
        if (!Intersector.intersectSegmentCircle(gunPosition, target, playerPosition, playerSize * playerSize)) {
            targetIsObscuredByPlayer = false;
            Vector2 gunToTargetDirection = new Vector2(target).sub(gunPosition);
            Vector2 gunToPlayerDirection = new Vector2(playerPosition).sub(gunPosition);
            float gunToTargetAngle = signedAngleBetween(gunDirection, gunToTargetDirection);
            float gunToPlayerAngle = signedAngleBetween(gunDirection, gunToPlayerDirection);

            float gttaS = Math.signum(gunToTargetAngle);
            float gtpaS = Math.signum(gunToPlayerAngle);
            float direction;

            if (gttaS == gtpaS) {
                if (Math.abs(gunToTargetAngle) < Math.abs(gunToPlayerAngle))
                    direction = gttaS;
                else
                    direction = -gttaS;
            } else {
                direction = gttaS;
            }

            gunRotation += direction * maxGunTurnSpeed * Gdx.graphics.getDeltaTime();
        } else
            gunRotation += playerDeltaRotation;

        gunRotation = wrapAngle(gunRotation);
        gunDirection.set(1.0f, 0.0f).rotate(gunRotation);

        camera.update();

        shapeRenderer.setProjectionMatrix(camera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
        renderPlayer();
        renderGun(targetIsObscuredByPlayer);
        renderTarget();
        shapeRenderer.end();
    }
}

```

# Answer
> 2 votes
Think of the gun as of being parented to the player (conceptually, it inherits player's transform (rotation)). That way, you only need to worry about the local angle (in local space, it's as if the orientation of the player never changes). It's because in 2D, the angles simply add up - see the image below:

So you can still use

```
Math.max(Math.min(localAimAngle, 360), 90)

```

(perhaps with some adjustments to the limit values). You just have to calculate the local aim angle first, which is just:

```
public static float clampMountedGunAngle(float aimAngle, float playerAngle) {

    float localAimAngle = aimAngle - playerAngle;
    localAimAngle = normalizeAngle(localAimAngle);  // make sure it's in 0-360 range

    // adjust the limits as necessary
    localAimAngle = Math.max(Math.min(localAimAngle, 360), 90);

    float result = playerAngle + localAimAngle;
    return normalizeAngle(result);
}

// Normalizes an angle to the 0-360 range
public static float normalizeAngle(float angle) {
    return angle - (float)Math.floor(angle / 360f) * 360f;
}

```

P.S. For a more sophisticated handling of the *behavior* of the gun, see bornander's answer.

P.P.S.

> Ok maybe your way can work in principle, but still it does not work at all as yet. The gun just stays fixed all the time for some reason - the whole angle range was a dead zone...not just between 360 and 90. Did you test it in an actual working program?

Here's a JavaScript snippet. I treated the gun as attached to the player, but with an independent orientation (assuming you want it to aim at something). The `gunAngle` in the code below is with respect to the global coordinate system, so if you don't change it, it will stay as it is. I adjusted the clamp and normalize functions to suit this setup (the two functions are at the top, after the vars):

```
const canvas = document.getElementById('canvas'),
context = canvas.getContext("2d");

const keyW = 87;
const keyS = 83;
const keyA = 65;
const keyD = 68;
let pressedKeys = [];

const originOffset = vec(250, 250);

let mouseLocation = vec(0, 0);

let playerAngle = 0;   // global coordinate sys (0 is up)
let playerLocation = vec(0, 0);
const playerRadius = 50;
const playerSpeed = 100;
const playerRotationSpeed = 100;

let gunAngle = 0;    // global coordinate sys (0 is up)
const gunRadius = 35;
const gunLocation_local = vec(0, playerRadius + gunRadius);
const gunDeadZone = 45;  // deg, +/- in both directions

let time = new Date().getTime();
let elapsed = 0;

function clampMountedGunAngle(aimAngle, playerAngle) {

  let localAimAngle = aimAngle - playerAngle;
  let adjustedAngle = localAimAngle + 90;
  adjustedAngle = normalizeAngle(adjustedAngle);

  const limitMin = -180 + gunDeadZone;
  const limitMax = 180 - gunDeadZone;

  adjustedAngle = Math.max(Math.min(adjustedAngle, limitMax), limitMin);
  localAimAngle = adjustedAngle - 90;

  const result = playerAngle + localAimAngle;
  return normalizeAngle(result);
}

// normalize to the -180 to 180 range
function normalizeAngle(angle) {
  let offsetAngle = angle + 180;
  offsetAngle = offsetAngle - Math.floor(offsetAngle / 360) * 360;
  return offsetAngle - 180;
}

function update() {
  const newTime = new Date().getTime();
  elapsed = newTime - time;

  pressedKeys.forEach(handleKey);

    const aimRay = getAimRay();
  gunAngle = -radToDeg(Math.atan2(aimRay.y,aimRay.x));

  gunAngle = clampMountedGunAngle(gunAngle, playerAngle);
  draw();

  time = newTime;
  requestAnimationFrame(update);
}

function draw() {
  context.clearRect(0, 0, 500, 500);

  context.save();
  context.globalCompositeOperation = 'source-over';
  context.translate(originOffset.x, originOffset.y);
  context.rotate(degToRad(-90));

  drawPlayer(context);
  drawGun(context);
  drawTarget(context);

  context.restore();
}

function drawPlayer(context) {
  context.save();
  context.translate(playerLocation.x, playerLocation.y);
  context.rotate(degToRad(-playerAngle));

  context.beginPath();
  context.fillStyle = "#999";
  context.arc(0, 0, playerRadius, 0, Math.PI);
  context.fill();

  context.beginPath();
  context.arc(0, 0, playerRadius, 0, 2*Math.PI);
  context.stroke();

  context.beginPath();
  context.moveTo(-playerRadius, 0);
  context.lineTo(playerRadius+20, 0);
  context.stroke();

  context.restore();
}

function drawGun(context) {
  context.save();

  context.translate(playerLocation.x, playerLocation.y);
  context.rotate(degToRad(-playerAngle));
  context.translate(gunLocation_local.x, gunLocation_local.y);
  context.rotate(degToRad(playerAngle - gunAngle));

  context.fillStyle = "rgba(255, 0, 0, 0.2)";
  context.strokeStyle = "#FF0000";

  context.beginPath();
  context.moveTo(0, 0);
  context.arc(0, 0, gunRadius, 0, 2*Math.PI);
  context.fill();

  context.beginPath();
  context.moveTo(0, 0);
  context.arc(0, 0, gunRadius, degToRad(-gunDeadZone), degToRad(gunDeadZone));
  context.fill();

  context.beginPath();
  context.moveTo(0, 0);
  context.arc(0, 0, gunRadius, 0, 2*Math.PI);
  context.lineTo(gunRadius+60, 0);
  context.closePath();
  context.stroke();

  context.restore();
}

function drawTarget(context) {
  context.save();
  context.translate(mouseLocation.x, mouseLocation.y);

  context.fillStyle = "rgba(255, 0, 0, 0.2)";
  context.strokeStyle = "#FF0000";

  context.beginPath();
  context.moveTo(0, 0);
  context.arc(0, 0, 5, 0, 2*Math.PI);
  context.fill();
  context.restore();
}

function getGunLocation() {
  const sinPlayer = Math.sin(degToRad(playerAngle));
  const cosPlayer = Math.cos(degToRad(playerAngle));
  const x = gunLocation_local.x;
  const y = gunLocation_local.y;
  let gunLocation = vec(
    cosPlayer * x + sinPlayer * y,
    -sinPlayer * x + cosPlayer * y);
  gunLocation = add(playerLocation, gunLocation);
  return gunLocation;
}

function getAimRay() {
  const gunLocation = getGunLocation();
  const aimRay = add(mouseLocation, mul(-1, gunLocation));
  return aimRay;
}

function handleKey(keyCode) {
    const elapsedSec = elapsed * 0.001;
    const direction = vec(
    Math.cos(degToRad(playerAngle)),
    -Math.sin(degToRad(playerAngle))
  );
  let delta = mul(playerSpeed * elapsedSec, direction);

  if ( keyCode == keyW ) {
    playerLocation = add(playerLocation, delta);
  }
  else if ( keyCode == keyS ) {
    delta = mul(-1, delta);
    playerLocation = add(playerLocation, delta);
  }
  else if ( keyCode == keyA ) {
    playerAngle += playerRotationSpeed * elapsedSec;
  }
  else if ( keyCode == keyD ) {
    playerAngle -= playerRotationSpeed * elapsedSec;
  }
}

function degToRad(deg) { return deg * Math.PI / 180; }
function radToDeg(rad) { return rad * 180 / Math.PI; }
function vec(x, y) { return ({ x, y }); }
function mul(a, vect) { return vec(a*vect.x, a*vect.y); }
function add(vecA, vecB) { return vec(vecA.x + vecB.x, vecA.y + vecB.y); }

function onKeyDown(e) {
  if (!pressedKeys.includes(e.keyCode))
    pressedKeys.push(e.keyCode);
}

function onKeyUp(e) {
  pressedKeys = pressedKeys.filter(k => k != e.keyCode);
}

function getMousePos(canvas, evt) {
  const rect = canvas.getBoundingClientRect();
  mouseLocation = vec(evt.clientX - rect.left, evt.clientY - rect.top);
  mouseLocation = add(mouseLocation, mul(-1, originOffset));

  // rotate 90 deg
  const x = mouseLocation.x;
  mouseLocation.x = -mouseLocation.y;
  mouseLocation.y = x;
}

window.addEventListener('keydown', onKeyDown, true);
window.addEventListener('keyup', onKeyUp, true);
canvas.addEventListener('mousemove', (e) => getMousePos(canvas, e), false);

requestAnimationFrame(update);
```

```
canvas {
    border: 1px solid gray;
}
```

```
<p>
  Use WASD to move (tank controls, click here first) + mouse to aim.
</p>
<canvas id="canvas" width="500" height="500">
</canvas>
```

---
Tags: java, libgdx, mathematics, angles
---


# Question
Title: Why should every light source have its own ambient light?
I'm currently learning how to use OpenGl, and I'm following a tutorial on learnOpenGL. I'm at the lightning chapter, and it has introduced basic lightning, ambient and diffuse with specular highlight. Phong shading essentially.

I'm confused about the ambient term. I understand that the ambient light is basically a light that comes from nowhere in particular, and it just fills the scene you're in with a soft light. And it's used to fake Global Illumination in renderers that do not compute it, so that the stuff that's not in the direct view of a light source is not completely black but it has some generic lightning on it.

So going by the definition, before actually trying to implement a renderer myself, and by using other engines like UE4, I always just assumed that ambient light would be a separate thing from say a point light or a directional light. I thought it would be a parameter independent of other stuff that would basically just light the scene.

But in the tutorial, at least for the basic lightning part, the ambient is actually part of the light "object" itself. Essentially every light source has its own ambient light.

This seems counterintuitive to me. Why does every light need an ambient part too? Wouldn't make more sense to have a "separate" ambient light object that provides the ambient light itself?

Also, if my light has a radius of say 100 units, then outside of that radius nothing will receive any direct light, obviously, but also no ambient and will be completely dark. Isn't the point of ambient light exactly not to have scenes without direct light go completely dark?

Most importantly I'm wondering if this implementation approach is the standard used in modern game engines, or if it's maybe a simplification in the tutorial. (For example I don't remember seeing a parameter for ambient light in the light objects themselves in UE4)

Links for context: https://learnopengl.com/Lighting/Basic-Lighting https://learnopengl.com/Lighting/Light-casters

# Answer
> 2 votes
> But in the tutorial, at least for the basic lightning part, the ambient is actually part of the light "object" itself. Essentially every light source has its own ambient light

If you consider ambient lighting to be global, then this is not the case. The *global* ambient term is essentially an extra light source that's independent of direction, that's added to the lighting calculation for *every object* (not for every light).

E.g., if you had multiple lights, it would be (pseudocode):

```
vec3 result = (ambient + diffuse1 + diffuse2 + ... + diffuseN) * objectColor;

```

Now, since ambient lighting can be colored, you need to specify a color for it too, not just a multiplier (e.g., in daylight, you might want it to have a sky-blue color, in a night scene that cinematic night-blue, in a lava-filled chamber you may want it to be orange-red, etc.)

I didn't read the tutorial very carefully, but I think they are using a single light source, and the color of that light is reused as the ambient color.

Now, you don't *have* to have only the global ambient illumination. Suppose you are in a room that's lit by two differently colored lights - in reality the light bounces off of the walls, so you'll have some global illumination coming from the surroundings that smoothly changes color depending on the direction. Or imagine a scene where you start outside, at night on the slope of a volcano (blue ambient color), and the enter a lava-filled cave (orange-red ambient color).

You can simulate this by adding a per-light ambient term that's attenuated with distance (and placing the light sources at appropriate locations). If you add an independent per-light multiplier for it, then you can have lights that only produce direct lighting, only ambient lighting, or both.

But that's not necessarily always done. You can do other things, e.g., you can change the global ambient color as you transition areas (but then, if you can still see the objects outside, they'll have wrong ambient lighting). You can have regions (boxes) that define ambient lighting within them, and somehow send location-specific ambient color to the shader. But then you'll have sharp jumps when object transition from one area to the next, unless you find a way to smooth that out over a couple of frames, or based on distance, or something like that. So, you know, tradeoffs.

---
Tags: opengl, lighting, shading
---


# Question
Title: Looking for a market price algorithm for a turn based game
I am new at game development and am now facing the problem for a market price algorithm in a turn based game. What I try to achieve:

* the market starts with fixed bidding and asking prices for one piece of goods. To keep it simple the minimum value is 1, the maximum 20
* if the user buys/sells the same goods in too large quantities in a certain amount of turns, the prices should rise/drop; simple supply and demand logic. The maximum amount of a goods per transaction is 100
* if the user doesn't trade that good for a few turns, it should adjust the price in the other direction
* there are certain type of goods that can be "easily" produced by the player and are thus sold and some that are harder to get by and are usually bought.
* the market can sell each good infinitely and would also buy everything, so it has no stock to take into account.

What I tried and didn't work:

* if the accumulated quantity of bought/sold good reaches 500 (I use negative values for buying) the price rises or drops by 1 respectively
* to factor the turns into it, I thought I just reduce the accumulated value by 10 each turn and then adjust the price if it reaches 0 again. This has one big flaw, as you can easily cheat by just selling a small amount, wait a few turns and the price will rise; repeat until the price reaches the maximum of 20.

Any simple ideas on how to fix this?

ps. I hope this is an appropriate question to ask here

# Answer
> 0 votes
Although I am not entirely sure what you are looking for I think your basic solution is okay, but probably needs to be a bit more refined to avoid issues of suspected "cheating". I hate to post an answer without more information on exactly what you want, a naive solution like mine below might help. The system uses a linear remapping function so it's not the most exciting implementation, but should be able to handle basic pricing. You might need something a bit more robust if you want deal with players trying to flood the market while prices are high (for example if someone is selling 5 items when the price is $20, you may want to pay the entire $100, but if they are selling 500, you may want to settle for paying $5 per item or $2,500 total rather than $10,000).

```
namespace Thomas.Game
{
    public class Item
    {
        public float popularity = 1.0f; // use if item is currently trending
        private int supply;
        private int minDemand;
        private int maxDemand;
        private int minPrice;
        private int maxPrice;
        private int minSupply; // should be 0 but can be higher if this should be held on to.
        private int maxSupply;
        private float buyBackAdjustment;
        private bool isSupplyUnlimited;

        Item(int initialSupply, int minSupply, int maxSupply, bool isSupplyUnlimited, int minDemand, int maxDemand, int minPrice, int maxPrice, float buyBackAdjustment)
        {
            this.supply = initialSupply;
            this.minSupply = minSupply;
            this.maxSupply = maxSupply;
            this.isSupplyUnlimited = isSupplyUnlimited;
            this.minDemand = minDemand;
            this.maxDemand = maxDemand;
            this.minPrice = minPrice;
            this.maxPrice = maxPrice;
            this.buyBackAdjustment = buyBackAdjustment;
        }

        public void Consume()
        {
            supply -= popularity * Random.Range(minDemand, maxDemand);

            if (supply < 0)
            {
                supply = 0;
            }
        }

        public bool CanSell(int amount)
        {
            return isSupplyUnlimited || (supply - amount) >= minSupply;
        }

        public void Sell(int amount)
        {
            supply -= amount;

            if (supply < 0)
            {
                supply = 0;
            }
        }

        public void Buy(int amount)
        {
            supply += amount;

            if (supply < 0)
            {
                supply = 0;
            }
        }

        public int GetSalePrice()
        {
            return (int)supply.RemapClamped(minSupply, maxSupply, maxPrice, minPrice);
        }

        public int GetBuyPrice()
        {
            return (int)(buyBackAdjustment * GetSalePrice());
        }
    }
}

namespace Thomas.Utility
{
    public static class FloatExtensions
    {
        public static float Remap(this float value, float from1, float to1, float from2, float to2)
        {
            return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
        }

        public static float RemapClamped(this float value, float from1, float to1, float from2, float to2)
        {
            return Mathf.Clamp(value.Remap(from1, to1, from2, to2), from2, to2);
        }
    }
}

```

---
Tags: game-design, algorithm
---


# Question
Title: Does SDL2 completely encapsulates Direct3D and OpenGL?
I'm starting to study game development but the concepts of how the SDL2 lib works are still a bit blurry to me.

I get that both Direct3D and OpenGL are two sides of the same coin. They both are used to draw vectors in the screen and are used as a graphics hardware abstraction layer.

From what I read about the SDL2 lib it seems to be a multi-purpose library that encapsulates some functionalities as user input, threading, networking, window creation, and so on \[and also "*graphics hardware **via** OpenGL and Direct3D*"\].

Now the questions:

1. The SDL2 webpage states that it provides access to "*graphics hardware **via** OpenGL and Direct3D*". What exactly that means?
2. If I'm making a 3D game do I need to decide beforehand which graphics API I want to use (Direct3D or OpenGL) and use it alongside with the SDL2? If not, does SDL2 completely encapsulates the graphics API so I could easily deploy my game targeting Direct3D or OpenGL without adapting too much code for each one?
3. In the case SDL2 does not completely abstract the graphics API, what texts and terms should I search to learn how to implement such an abstraction layer using SDL2? I want to be able to easily build for Direct3D and OpenGL.

Thanks very much!

# Answer
SDL is a library which hides the graphics API behind a more convenient abstraction layer.

When you want to draw a sprite using the SDL library, you would call the function `SDL_RenderCopy(renderer, texture, srcRect, dstRect);`.

This function will then internally call the respective function of the graphics API to accomplish this. Which function of which API? That depends on the platform you are compiling your game for. When you compile for Windows, it will use Direct3D. When you compile for Linux, it will use OpenGL.

The purpose of using a library like SDL is that you no longer need to care about what graphics API is used by your game, which target platforms support which APIs and what the unique peculiarities of those APIs are. SDL hides all this behind one unified API.

However, the SDL graphics functions only do 2d graphics. When you want 3d graphics, then SDL doesn't give you much for that. So you will have to find a different solution for putting your 3d models onto the screen. But there is still some functionality of the SDL library besides graphics which can be useful for a 3d game which doesn't do its rendering through SDL:

* Loading and parsing asset files
* Audio playback (although the SDL audio API is rather spartanic in this regard)
* Input handling
* Filesystem abstraction
> 1 votes

# Answer
**You still need to use the actual API**.

For OpenGL, SDL will handle the platform-specific parts, so for most use cases that involves creating a window, creating an OpenGL context, and issuing SwapBuffers calls. Once you have an OpenGL context up and running you just use the regular OpenGL API as normal.

SDL 1.2 documentation for OpenGL is here: https://www.libsdl.org/release/SDL-1.2.15/docs/html/guidevideoopengl.html

> Apart from initialisation, using OpenGL within SDL is the same as using OpenGL with any other API.

For Direct3D there is no encapsulated initialization, so instead you must create your window using SDL, retrieve it's window handle, then initialize and use Direct3D as normal via standard Direct3D API calls.
> 1 votes

---
Tags: opengl, directx, sdl2
---


title: Why do we need more than 24 FPS?

text:
# Question
Title: Why do we need more than 24 FPS?
Many movies (probably, all moovies, except for the most recent ones) have 24 frames per second, and we're quite happy with it. There is a thing called "Subliminal stimuli" or "Subliminal message" - in Russian it is called simply - "25th frame". It means that somebody inserts some picture (e.g. advertisement) every 25th frame in usual movie and it influences the watcher, though the watcher does not see it. It does not really matter whether it really influences the watcher or not. The important thing - is that we don't see it. For me personally, the most easy way to improve performance in a game - is to limit FPS, usually up to 30 , if a game allows it. So if we're happy with 24 frames per second and we do not see the 25th frame - why do we try to get more and more FPS in games? 60, 70, 100, 120? Why the whole industry is trying to draw frames which we do not see?

# Answer
> 3 votes
The number of frames a human can perceive per second is not a constant number. It depends on a lot of factors.

* Age. Younger people can perceive more FPS than older people. High-fidelity 3d games often target demographics of teenagers and young adults, who have a better animation perception than older people.
* Interactivity. When the viewer does not control the images in real-time (like when watching a movie), then lower FPS are less noticeable than when the viewer controls the perspective in real-time (like in a game). Which is why some games render cutscenes with 30FPS but the game itself with 60FPS and more.
* Type of motion. When watching a static object, then lower FPS are less noticeable than when the object moves around the screen. Objects which move around the screen quickly require a higher framerate to be perceived as fluid than those which move slowly.
* How sharp the images are. More blurry images can get away with slower framerates. Analog film has natural motion blur, which allows lower framerates. 3d rendered animation doesn't, unless you add artificial motion blur as a post-processing filter.
* Brightness, contrast and even the colors used in a scene can be relevant.

Depending on these factors, 30 FPS or even less can be good enough, you might need 60 FPS or some people might even see a difference with 120 FPS.

Here is a web application where you can experiment with different framerates for different kinds of motion and see if you can perceive a difference in quality.

---

And by the way, 24 FPS used to be the traditional framerate for movies, but there are also movies which run in higher framerates. Also, many modern TVs have techniques to interpolate between frames to double the framerate of classic 24 FPS movies and tv programs. Most viewers do perceive the difference.

# Answer
> 1 votes
This varies wildly between people and is also affected by the screen technology in use. I spent years gaming at 24 fps on an IBM T221 monitor and perceived as perfectly smooth as long as it was 24 fps, always fps, and never a single frame got dropped. As long as the delay between the frames is perfectly consistent (i.e. you get a frame *every* 1/24 of a second).

I know people who claim that even 60 seems juddery.

Personally, I struggle to tell the difference between a 100% stable 30fps and 60fps, but I can tell a huge difference between different monitors in terms of the amount of motion blur caused by the panel even at a perfectly stable frame rate.

A lot of this comes from the fact that digital display panels suffer from additional lag, motion blur (blanking time is measured grey-to-grey rather than black-to-black, hence why recently there have been technologies like 120Hz displays that insert a completely black frame between two real frames). For example, going from 50Hz to 100Hz will give you an extra 10ms of reaction time, but higher refresh rate screens also have lower lag between receiving the frame and rendering it, which will gain you up to another few 10s of milliseconds, all of which can add up to a measurable competitive gaming advantage.

In terms of persistence of vision, 24 fps is sufficient for perception of fluid motion for most people. Various deficiencies of technology result in requirements being much higher to hide those deficiencies.

Or to put it differently, in a perfect world, a lower refresh rate may well be sufficient for many people, but all technology tends to be built upon many layers of compromises, each of which necessitates higher and higher refresh rates to hide the imperfections.

---
Tags: performance, frame-rate
---


title: Rotation matrix to look at point p

text:
# Question
Title: Rotation matrix to look at point p
Assume a left-handed coordinate system where x is right, y is up, and z is into the screen. You have a unit vector pointing up along the y-axis. What's the rotation matrix for pointing the unit vector along the y-axis to an arbitrary point p?

I was asked this question during a phone screen. The interviewer implied there's an easy way to get this rotation matrix by "dropping in" a few values. I'm reading a 3D math book hoping to find this easy way but no luck yet. The ways to get this matrix in the book all seem too long to recite over the phone during an interview.

I think I can see part of the solution. The rows of the matrix are the post-transformation basis vectors. So the middle row of the matrix is just the point p possibly normalized (since that's where the y-axis will be post-rotation).

Any help with this easy "drop in" way of getting the rotation matrix is much appreciated!

**Edit**: If it seems like the problem statement is missing information please call it out. I feel like I remember the interview clearly but I could have left something out (or the interviewer could have).

# Answer
First let's get the direction we want our y vector to point:

```
yDirection = Normalize(p - viewPoint);

```

(Here viewPoint can be the origin, since it doesn't look like you were given a specific location for the observer)

If this works out to be the zero vector then we need to fall back on some sensible default, which I'll elide here.

There's an infinite number of rotation matrices that will map the local y+ axis to point along `yDirection` (take any matrix that does this, and apply an extra rotation around the axis `yDirection`: now you have a new distinct matrix that still does what we asked), so we'll need to make some arbitrary choices here.

Let's decree that our rotation will take the local x+ axis and map it into the world xz plane. We always have at least one way to do this while staying perpendicular to `yDirection`. If we have a whole plane of choices, then we'll just map it to the world x+ axis by fiat.

```
xDirection = Cross((0, 1, 0), yDirection);

if (xDirection == (0, 0, 0)) {
     xDirection = (1, 0, 0);
} else {
     xDirection = Normalize(xDirection);
}

```

Now we have two perpendicular unit vectors to map x and y to. We can cross them to get the remaining z:

```
 zDirection = Cross(xDirection, yDirection);

```

And finally we can combine the three into a rotation matrix, whose first column is `xDirection`, second column is `yDirection`, and third column is `zDirection`. (Assuming you multiply `Matrix * vector`. If you go `vector * Matrix`, then use these direction vectors as the matrix's rows instead)

I work through this relationship in more detail in this answer.
> 1 votes

---
Tags: mathematics, rotation, matrix
---


# Question
Title: Change transform.localPosition to act like transform.Translate with Space.Self
I run into the problem with moving object regarding to its rotation. The thing is that I'm changing object position by assigning new `transform.localPosition` value. In specific cases I want to modify assigned value by slightly changing `z` axis (height) of the object.

I tried to do it with use of `transform.up`. I expected move along local `z` axis (like in Unity scene preview), but it doesn't work as expected.

`transform.Translate(Vector3.up, Space.Self)` works exactly as I want, but as I said I want to combine it with `transform.localPosition` i already use. How should I modify passed Vector3 so it works correctly?

---

The class below is used to simulate move of an object around sphere. For example plane flying around Earth. I adjust plane rotation so it's chassis is facing Earth. Object is moving on the Earth surface though. I want to move it slightly up so it flies. That's why I want to move it along local `z` axis as it is distance from the core of the Earth.

Full class snippet (I'm using LeanTouch package)

```
public Transform lookAtTarget;
RaycastHit hit;
RaycastHit lastHit;

public float rotationSmoothTime = 0.3F;
public float moveSmoothTime = 0.3F;
private Vector3 rotationVelocity = Vector3.zero;
private Vector3 moveVelocity = Vector3.zero;
private Vector3 lastNewRightDir;

protected virtual void Awake ()
{
    Use.UpdateRequiredSelectable (gameObject);
    lastNewRightDir = transform.right;
}

void Update ()
{
    var fingers = Use.GetFingers ();
    if (fingers.Count < 1)
    {
        Move (lastFingerScreenPosition, Vector2.zero);
        return;
    }
    LeanFinger finger = fingers[0];
    Move (finger.ScreenPosition, finger.ScreenDelta);
    lastFingerScreenPosition = finger.ScreenPosition;
}

public void Move (Vector2 fingerScreenPosition, Vector2 scaledDelta)
{
    var ray = Camera.main.ScreenPointToRay (fingerScreenPosition);
    LayerMask mask = LayerMask.GetMask ("Interactable");

    bool newHit = Physics.Raycast (ray, out hit, float.PositiveInfinity, mask);

    Vector3 rightDir = transform.right;
    Vector3 newRightDir = lastNewRightDir;

    Vector3 targetPosition = lastHit.point;

    if (newHit)
    {
        targetPosition = hit.point;
        lastHit = hit;
    }
    else if (lastHit.distance == 0)
    {
        return;
    }

    Vector3 forwardDir = (targetPosition - lookAtTarget.position).normalized;

    if (targetPosition != transform.position && scaledDelta != Vector2.zero)
    {
        newRightDir = (targetPosition - transform.position).normalized;
        lastNewRightDir = newRightDir;
    }

    rightDir = Vector3.SmoothDamp (rightDir, newRightDir, ref rotationVelocity, rotationSmoothTime);
    Vector3 upwardDir = Vector3.Cross (forwardDir, rightDir);
    transform.rotation = Quaternion.LookRotation (forwardDir, upwardDir);

    transform.localPosition = Vector3.SmoothDamp (transform.localPosition, targetPosition, ref moveVelocity, moveSmoothTime);
}}

```

Before `transform.localPosition = Vector3.SmoothDamp (transform.localPosition, targetPosition, ref moveVelocity, moveSmoothTime);` the `targetPosition` value should be adjusted so object moves 1 unit alongside local z axis.

# Answer
`transform.up` is a vector in world space, but `transform.localPosition` moves an object in its *parent's* space. If the parent (or grandparent, etc) is rotated, then these two spaces can differ.

To get the object's up vector relative to its parent coordinate system, just multiply:

```
Vector3 localUpInParentSpace = transform.localRotation * Vector3.up;

```

Then you can add it to your localPosition:

```
upwardShift = 1.0f; // Substitute whatever distance you want to move here.
Vector3 shiftedLocalPosition = transform.localPosition + localUpInParentSpace * upwardShift;

```

This moves along the object's local y+ axis. If you want to move along the object's local z+ axis, use `Vector3.forward` instead of `Vector3.up`.
> 2 votes

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


# Question
Title: how to find the game engine of an app in play store
I would like to know if there is a way to find which game engine a game uses, **especially** games that are on **play store**

Also I want to know if decompiling the app will help?

if there is another way to get the engine without going through decompiling it would be great to know it

# Answer
> 2 votes
Short version... No. There's nothing listed on the store that would tell you that (unless the dev includes it in the description).

Most marketplaces don't attempt to identify the technologies used (unless they come from the same source) and ultimately, the only technical requirement they're interested in is whether it will run on the target platform.

Also... It's worth noting that many games don't use a standard engine and are just coded directly (as mentioned in the comments this often results in the development of custom in-house engines that are used/evolved across multiple games).

# Answer
> 0 votes
You find the developer's contact information and ask them. Maybe they'll have time and be kind enough to answer.

---

However, as it's been mentioned in the comments, having the infromation is most likely irrelevant.

If a wood sculptor is very proficient with a chainsaw, but you're an ace with an angle grinder, you'll probably end up creating better looking wood statues using angle grinder than if you clumsily used a chainsaw. Similarly, it's not because you know they have used engine X that you'll know how to use engine X to achieve similar results.

An engine is just a tool to an end. Use the tool you're the most comfortable with to get to that end.

That being said, even if you know they used X to get result Y in game Z, if you end up with result Y too, chances are that you'll be accused of copying Z in the playstore comments for your game.

---
Tags: android, google-play
---


# Question
Title: Is Goal-Oriented Action Planning (GOAP) a valid replacement for state machines outside the realm of AI?
I just learned about Goal-Oriented Action Planning (GOAP, sources below) as used in AI programming. I'm making a state machine for a player-controlled character and was wondering if it can be replaced by a GOAP model? Does this make sense? Or is GOAP only for AI?

Sources:

# Answer
> 2 votes
I assume that you mean a character whose every action is controlled by the player (e.g. the style commonly seen in everything from FPS, platforming, action-adventure, etc). This is in contrast to characters in say, an RTS game, where something like GOAP may be completely appropriate.

Planning systems are commonly bundled with a goal-selection system (e.g. agents ask "What is my most important priority?"), which typically boils down to goals individually emitting real-valued "activation levels" and the system planning to achieve the goal with the highest activation level.

This makes it particularly difficult to apply to player-controlled characters. When you press the left key, for instance, you want him to move left *now*, rather than having the "move left" goal's activation level increase in value, hoping that is beats out whatever the currently active goal is, and then having the planner eventually find a sequence of actions that will lead to moving left.

At some point, all of your planning systems have to resolve to something that "does the right thing" (see the famous paper: http://people.csail.mit.edu/brooks/papers/Planning%20is%20Just.pdf). In the case of player controls, you always want to do the right thing, which makes planning seem inappropriate.

# Answer
> 0 votes
GOAP is only for AI. While a player character's scripts can influence or be influenced by it, GOAP's planning system is tailored to function primarily for AI. Finite states will serve you best for player character controls.

---
Tags: architecture, ai, state
---


title: Help with inventory!

text:
# Question
Title: Help with inventory!
Ok so i made this inventory script but the items are not picking up and not appearing in the inventory. Im new to c# so that is why im asking this question also ive never done an inventory before. I want the medkit to go in the medkit slot. And bandage in the bandage slot and so on. Here are my scipts.

Here is my inventory script attached to the player.

```
public class MedInventory : MonoBehaviour
{
    public bool[] isFull;
    public GameObject[] MedkitSlot;
    public GameObject[] BandageSlot;
    public GameObject[] CoffeeSlot;
    public GameObject[] SyringeSlot;
}

```

Here is the medical pickup script attached to the item pickup.

```
public class MedPickup : MonoBehaviour
{
    private MedInventory medInv;
    public GameObject itemButton;

    private void Start()
    {
        medInv = GameObject.FindGameObjectWithTag("Player").GetComponent<MedInventory>();
    }

    void OnTriggerStay2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            if (other.CompareTag("medkit"))
            {
                for (int i = 0; i < medInv.MedkitSlot.Length; i++)
                {
                    if (medInv.isFull[i] == false)
                    {
                        medInv.isFull[i] = true;
                        Instantiate(itemButton, medInv.MedkitSlot[i].transform, false);
                        Destroy(gameObject);
                        break;
                    }
                }
            }

            if (other.CompareTag("bandage"))
            {
                for (int i = 0; i < medInv.BandageSlot.Length; i++)
                {
                    if (medInv.isFull[i] == false)
                    {
                        medInv.isFull[i] = true;
                        Instantiate(itemButton, medInv.BandageSlot[i].transform, false);
                        Destroy(gameObject);
                        break;
                    }
                }
            }

            if (other.CompareTag("coffee"))
            {
                for (int i = 0; i < medInv.CoffeeSlot.Length; i++)
                {
                    if (medInv.isFull[i] == false)
                    {
                        medInv.isFull[i] = true;
                        Instantiate(itemButton, medInv.CoffeeSlot[i].transform, false);
                        Destroy(gameObject);
                        break;
                    }
                }
            }

            if (other.CompareTag("syringe"))
            {
                for (int i = 0; i < medInv.SyringeSlot.Length; i++)
                {
                    if (medInv.isFull[i] == false)
                    {
                        medInv.isFull[i] = true;
                        Instantiate(itemButton, medInv.SyringeSlot[i].transform, false);
                        Destroy(gameObject);
                        break;
                    }
                }
            }
        }
    }
}

```

Please help and thanks!

# Answer
It looks like you are checking the same *"other"* **GameObject** in your **OnCollisionStay** function for **two different tags**. This should successfully identify your player (assuming they are tagged as *"Player"*) but will skip all code adding items to their inventory (since the player is not tagged *"medkit"*, *"bandage"*, etc.). You should be able to fix this by checking your pickup **gameobjects tag**.

I apologize if the code sample below is confusing (I figured since you are new to coding cleaning up the script a little might be helpful as an example), the key take away is that instead of calling **gameObject.tag** to check the current pickup item type instead of **other.ComapreTag**. You may also want to look into using interfaces/subclasses for your items since they should probably fit and it would let you avoid having a separate array for each item type.

```
public class MedPickup : MonoBehaviour
{
    private MedInventory medInv;
    public GameObject itemButton;

    private void Start()
    {
        medInv = GameObject.FindGameObjectWithTag("Player").GetComponent<MedInventory>();
    }

    void OnTriggerStay2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            GameObject[] targetSlot = new GameObject[0]; // need to initialize this to something to avoid compiler error.
            bool validItem = true;

            switch (gameObject.tag)
            {
                case "medkit":     targetSlot = medInv.MedkitSlot;     break;
                case "bandage":    targetSlot = medInv.BandageSlot;    break;
                case "coffee":     targetSlot = medInv.CoffeeSlot;     break;
                case "syringe":    targetSlot = medInv.SyringeSlot;    break;
                default:           validItem = false;                  break;
            }

            if (validItem)
            {
                for (int i = 0; i < targetSlot.Length; ++i)
                {
                    if (!medInv.isFull[i])
                    {
                        medInv.isFull[i] = true;
                        Instantiate(itemButton, targetSlot[i].transform, false);
                        Destroy(gameObject);
                        break;
                    }
                }
            }
        }
    }
}

```
> 1 votes

---
Tags: unity, 2d, inventory
---


# Question
Title: How can I change the object to move on the waypoints to move also in reverse?
Now it's moving from the first position the last position and then in the end it's moving to the first position and then moving forward on all positions again and so on.

I want to use a flag bool variable that if it's true when the object to move on the waypoints will get to the last position it will then travel backward reverse on the positions and when it will get to the first one it will start moving forward again and so on like a ping pong. and if the bool flag is false it will be like now.

I'm not sure how to handle the line :

```
index = (index + 1) % pos.Length;

```

Not sure what the percentage % does in this line.

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

public class MoveOnCurvedLine : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public GameObject objectToMove;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;

    // Start is called before the first frame update
    void Start()
    {
        pos = GetLinePointsInWorldSpace();

        if (moveToFirstPositionOnStart == true)
        {
            objectToMove.transform.position = pos[index];
        }
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector
        lineRenderer.GetPositions(positions);

        //the points returned are in world space
        return positions;
    }

    // Update is called once per frame
    void Update()
    {
        if (go == true)
        {
            Move();
        }
    }

    void Move()
    {
        Vector3 newPos = objectToMove.transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        bool stillTraveling = true;
        while (stillTraveling)
        {
            Vector3 oldPos = newPos;
            newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
            distanceToTravel -= Vector3.Distance(newPos, oldPos);

            if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
            {
                index = (index + 1) % pos.Length;
            }
            else
            {
                stillTraveling = false;
            }
        }

        objectToMove.transform.position = newPos;
    }
}

```

I tried to do it this way :

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

```
public class MoveOnCurvedLine : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public GameObject objectToMove;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;
    private bool isreverse = false;

    // Start is called before the first frame update
    void Start()
    {
        pos = GetLinePointsInWorldSpace();

        if (moveToFirstPositionOnStart == true)
        {
            objectToMove.transform.position = pos[index];
        }
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector
        lineRenderer.GetPositions(positions);

        //the points returned are in world space
        return positions;
    }

    // Update is called once per frame
    void Update()
    {
        if (go == true)
        {
            Move();
        }

        if (index == pos.Length - 1)
        {
            System.Array.Reverse(pos);
            isreverse = true;
        }
    }

    void Move()
    {
        Vector3 newPos = objectToMove.transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        bool stillTraveling = true;
        while (stillTraveling)
        {
            Vector3 oldPos = newPos;
            newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
            distanceToTravel -= Vector3.Distance(newPos, oldPos);

            if (isreverse)
            {
                if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
                {
                    index --;// % pos.Length;
                }
                else
                {
                    stillTraveling = false;
                }
            }
            else
            {
                if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
                {
                    index = (index + 1) % pos.Length;
                }
                else
                {
                    stillTraveling = false;
                }
            }
        }

        objectToMove.transform.position = newPos;
    }
}

```

And it's moving in reverse when it's getting to the last position but there is a problem :

Each time it's getting to the last position the object to move is stuck and shaking like it's trying to move back to forward but stay in place and shaking and then after few seconds it's starting moving back in reverse. Why it happens ?

# Answer
> 1 votes
In C# % is to modulo/modulus operator. Essentially what it does is if left value exceeds the right value, subtract the right value until it is less than the right. Not the best explanation but as @DMGregory said, you can/should look it up if you want to better understand it's meaning. I would strongly recommend doing so since it is very important when working with Lists and Arrays.

As for your script issue. Thank you for posting what you tried, that is pretty rare these days. It looks like your problem comes from calling System.Arrays.Reverse() and switching the increment value of your index. Basically you are going backwards in a reversed list (so forwards again). That's probably where your code is freaking out. You should be able to find these issues using C# break points (seriously look this up, it is a life saver) and Unity debug statements.

I've mocked up a quick untested solution that should hopefully help but you may need to tweak it a bit to your liking.

```
public class MoveOnCurvedLine : MonoBehaviour
{
    #region Nested Classes

    public enum PlayMode
    {
        OneShot,
        Loop,
        PingPong
    }

    #endregion

    #region Fields

    [Header("Linked Scene Objects")]
    public LineRenderer lineRenderer;
    public GameObject objectToMove;

    [Header("Settings")]
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;
    public PlayMode playmode = PlayMode.Loop;

    private Vector3[] pos;
    private int index = 0;
    public bool isForward = true;

    #endregion

    #region MonoBehaviour Methods

    // Start is called before the first frame update
    private void Start()
    {
        pos = GetLinePointsInWorldSpace();
        index = isForward ? 0 : pos.Length - 1;

        if (moveToFirstPositionOnStart)
        {
            objectToMove.transform.position = pos[index];
        }
    }

    // Update is called once per frame
    private void Update()
    {
        if (go)
        {
            Move();
        }
    }

    #endregion

    #region Private Methods

    private Vector3[] GetLinePointsInWorldSpace()
    {
        Vector3[] positions = new Vector3[lineRenderer.positionCount];
        lineRenderer.GetPositions(positions); // Get the positions which are shown in the inspector
        return positions; // the points returned are in world space
    }

    private void Move()
    {
        Vector3 newPos = objectToMove.transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        while (go && distanceToTravel > 0.0001f)
        {
            Vector3 oldPos = newPos;
            Vector3 nextPos = pos[index];
            newPos = Vector3.MoveTowards(oldPos, nextPos, distanceToTravel);

            distanceToTravel -= Vector3.Distance(newPos, oldPos);

            if (newPos == nextPos) // Vector3 comparison is approximate so this is ok
            {
                if (isForward)
                {
                    index--;

                    switch (playmode)
                    {
                        case PlayMode.Loop:
                            index = (index + pos.Length) % pos.Length;
                            break;
                        case PlayMode.OneShot:
                            if (index < 0)
                            {
                                go = false;
                                index = 0;
                            }
                            break;
                        case PlayMode.PingPong:
                            if (index < 0)
                            {
                                isForward = !isForward;
                                index = 0;
                            }
                            break;
                    }
                }
                else
                {
                    index++;

                    switch (playmode)
                    {
                        case PlayMode.Loop:
                            index = index % pos.Length;
                            break;
                        case PlayMode.OneShot:
                            if (index >= pos.Length)
                            {
                                go = false;
                                index = pos.Length - 1;
                            }
                            break;
                        case PlayMode.PingPong:
                            if (index >= pos.Length)
                            {
                                isForward = !isForward;
                                index = pos.Length - 1;
                            }
                            break;
                    }
                }
            }
        }

        objectToMove.transform.position = newPos;
    }

    #endregion
}

```

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


# Question
Title: How to create transfer function for temperature in 2D space
I am looking for ways that can transfer temperature from tiles to tiles in space such as in Rim World, when you click on a tile, it will display the temperature on that particular tile and you can regulate the temperature in a confine space by installing air conditioner. Wonder is there any method in unity that can perform such function? Would like to learn it by myself. I am new to programming so not even sure where should I start my search.

# Answer
> 2 votes
First of all, I am making a couple assumptions which are not explicitly written in the question but I consider very likely to be true (because that's how it works in Rimworld). When any of these are incorrect, please drop a comment and also update the question.

* Your game world is tile-based. So you don't need temperature at arbitrary points, just on a tile-based resolution.
* The game world is a rectangle with a limited width and length.
* Heat spreads slowly across tiles, not instantly.
* You already know how to detect clicks on tiles and derive the tile coordinates in your click event.

Under these premises I would actually not rely too much on what Unity can do for me and rather roll my own solution in form of a cellular automaton.

I would create one new gameObject "TemperatureSystem" with a script of the same name. That script has a private two-dimensional array of float's with the same size as the game tilemap. This array represents the temperature of each tile.

The script would also offer a public method which allows other scripts to read the heat at a specific tile. This method should be used by other game mechanics which take heat into account. I would also add another public method to increase or decrease the heat value of a specific tile. This is for objects which change heat, like heaters or air conditioners. Such an object would in most cases only change the heat of the one tile it is on and then rely on the TemperatureSystem to dissipate the change to the surrounding.

The Update-method of my TemperatureSystem would then derives the new heat value of each cell from the old value of itself and the old value of its neighbors.

1. Create a copy of your heat values (the new values).
2. Iterate over the *old* heat values and:

1. Calculate the heat difference between this tile and its right neighbor by subtracting the neighbor heat value from its own heat value (use the old values, not the new ones)
    2. Determine the amount of heat being transferred between the tiles by multiplying that value with your desired rate of heat spread and Time.deltaTime. You might modify the heat spread multiplier depending on the materials of the two tiles. So some materials might work as heat insulators while others might work as heat conductors. But remember that the heat taken from a tile should be equal to the heat given to another. Otherwise you violate conservation of energy.
    3. Change the heat values in the *new* array by subtracting that amount from the current tile and adding it to the neighbor tile
    4. Repeat steps 1-3 for the lower neighbor
3. Replace the *old* heat values with the *new* ones.

---

By the way: There are a lot of other applications for cellular automatons in tile-based or block-based games. You can, for example, use them for:

* Air pressure in a space vessel
* Flow of liquids
* Spreading of fire (where you usually work with spread probability instead of constant spread rate)
* Plant growth

---
Tags: unity
---


title: Rotation grid positions

text:
# Question
Title: Rotation grid positions
I'm dealing with objects on 15x15 chunks in my game.

I'd like the chunks to rotate, for example, rotation version 0 is the original position of 2,5;

(EDIT: Oops, rotation 2 and 3 names need switching in the image)

How can I get the other positions in the simplest and quickest way? It only needs to rotate in 90 degrees increments, having 4 version (so 0, 90, 180, 270)

# Answer
> 9 votes
If horizontal axis is `x`, vertical is `y`, and chunk size is `n`, then clockwise rotation can be performed as follows:

```
(x2, y2) = (n - 1 - y1, x1)

```

and counter-clockwise rotation would be:

```
(x2, y2) = (y1, n - 1 - x1)

```

# Answer
> 12 votes
If you number the grid from the middle as (0,0), rather than the edge, rotating becomes as simple as

```
(x2, y2) = (-y1, x1)

```

You can still provide the grid to your player with conventional numbering, of course.

# Answer
> 7 votes
If you use Weckar's suggestion to number the grid with (0,0) in the center, this is specialized case of the general rotation formula. You could get any rotation using these equations

```
new_x = old_x * cos(angle) - old_y * sin(angle)
new_y = old_x * sin(angle) + old_y * cos(angle)

```

In your case, angle can only be 0, 90, 180, and 270, which means the sins and cosines can only produce values of -1, 0, and +1.

---
Tags: mathematics, rotate
---


# Question
Title: How can I provide an instance of a certain script to all scripts that need it?
# Problem

Whenever a player is added to the game (in the form of the server instantiating a player Game Object with a `Player` component), I want to provide it to every script that needs a reference; in other words, dependency injection.

# Potential Solutions

I thought I'd create an `IPlayerRequester` interface and have the `Player` script look up all implementing scripts on the client when it's created, but Unity has no interface-searching equivalent of `FindObjectsOfType<>()`.

# More Info

The game is multiplayer, where 1 player is the host — a client *and* the server — that is joined by other clients.

I'm using Mirror.

When a new client is added, the `Player` script's (that was just spawned) callback `OnStartLocalPlayer()` is invoked, and so far, that's the only way I've found to access the local environment.

But because this is the same `Player` that I'm trying to inject into requesting scripts, I can't just raise an event in that method, so that's out.

---

What would be a good solution here?

# Answer
you can create a List of players:

```
List<Player> players;

```

and use it for a group them all and iterate with a loop to apply them some operations. can play with it + the constructor to setting up all the stuff.

if it doesn't work u got delegates + events (a bit more advanced)

(Im not Unity dev but hope it helps)
> -1 votes

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


# Question
Title: How do I reduce the size of my symbols.zip?
I am making an Android app in Unity. Google recommends using a symbols.zip, which Unity auto-generates. However, the symbols.zip that Unity is generating for my app is over 1 GB, and the max size that Google will accept is 300 MB.

How can I reduce the size of my symbols.zip?

# Answer
If you are using Windows to zip, do not zip the originally extracted folder. Zip the contents of it, then rename.

https://stackoverflow.com/questions/63544670/unity-android-build-symbols-zip-file-too-big/64267680#64267680
> 0 votes

# Answer
If you haven't solved this yet I ran into the same problem and the solution is stupidly simple: Unpack the symbols.zip file and repack it.

You'll hopefully get an ok sized symbols file. It seems that Unity is simply very bad at compressing.

*edit* Rename the compressed file to the same name as the original file

Source
> 1 votes

# Answer
I believe Symbols.zip contains debugging symbols used for generating stack traces when an error occurs. It should be safe to remove this, though you might have difficulty diagnosing crash reports.

As an aside, if you're getting 1GB of symbols in a non-debug build, it sounds like something is going wrong with the build system, so this might be something worth reporting to Unity using the bug reporter.
> 0 votes

---
Tags: unity, android
---


# Question
Title: Geometry shader vertex position to point at camera
I have a shader that takes an array of points. At each point, a geometry shader creates a quad oriented towards the camera.

This works fine when the camera and point are at around the same Y value, however, looking up/down upon the billboard results in it shrinking to a point the closer the camera approaches being directly above/below.

Example (Youtube)

```
[maxvertexcount(4)]
void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
    // Calculate some vectors
    float3 up = float3(0, 1, 0);
    float3 look = _WorldSpaceCameraPos - IN[0].position;
    look = normalize(look);
    float3 right = cross(up, look);

    // And how far off-centre our corners are
    float halfS = 0.5f * IN[0].colorScale[1] * _Scale;

    // Calculate verts
    float4 v[4];
    v[0] = UnityObjectToClipPos(IN[0].position + float4(+halfS * right - halfS * up, 1.0f));
    v[1] = UnityObjectToClipPos(IN[0].position + float4(+halfS * right + halfS * up, 1.0f));
    v[2] = UnityObjectToClipPos(IN[0].position + float4(-halfS * right - halfS * up, 1.0f));
    v[3] = UnityObjectToClipPos(IN[0].position + float4(-halfS * right + halfS * up, 1.0f));

    // pass through color texture lookup
    float2 color = float2(IN[0].colorScale[0], .5);

    // Start pushing verts
    g2f o;
    o.position = v[0];
    o.color = color;
    o.uv = float2(1.0f, 0.0f);
    triStream.Append(o);

    ...

```

I'm guessing my issue is related to the fact that my `up` and `look` are approaching coincidence, as the forward derives directly from the camera and the up is in world space, however, I'm uncertain of my diagnosis and unclear on how to generate an appropriately rotated `up`?

# Answer
```
float3 look = _WorldSpaceCameraPos - IN[0].position;
look = normalize(look);

// TODO: if Look is completely vertical, choose a different up
float3 up = float3(0, 1, 0);

// Normalize your right vector to be sure it's unit length.
// (Otherwise it approaches 0 length as up and look become parallel)
float3 right = normalize(cross(up, look));

// Choose a new up vector perpendicular to both look and right.
up = cross(look, right);

```
> 1 votes

---
Tags: unity, shaders, hlsl, geometry-shader
---


# Question
Title: OBB vs rectangle/quad/plane with bounds collision detection/response
I am able to resolve collision between an OBB and a plane but can't get it to work when I introduce some bounds on the plane size. I want to have the plane of `width` and `height` dimensions defined by a `normal` and a `position`.

The code for detecting/resolving is fairly simple if the plane doesn't have any bounds:

```
function obbIntersectsPlane( obb, plane ) {
  let r = obb.size.x / 2 * Math.abs( dot( obb.right, plane.normal ) ) +
          obb.size.y / 2 * Math.abs( dot( obb.up, plane.normal ) ) +
          obb.size.z / 2 * Math.abs( dot( obb.forward, plane.normal ) );

  let s = dot( plane.normal, obb.position ) - dot( plane.normal, plane.position );

  if ( Math.abs( s ) < r ) {
    return {
      overlap: r - s,
      vector: plane.normal
    };
  }

  return false;
}

```

# Answer
Taking the plane as an obb with `depth=0` works fine for me. I had to modify how I calculated overlap though to account for cases when the projection of one object was fully inside the other object's projection.

```
let overlap;

// check for cases when the projection is fully inside the projection of the other object

if ( a_max > b_max && a_min < b_min ) {
    overlap = Math.min( a_max - b_min, b_max - a_min );
} else if ( b_max > a_max && b_min < a_min ) {
    overlap = Math.min( b_max - a_min, a_max - b_min );
} else {
    overlap = Math.min( a_max, b_max ) - Math.max( a_min, b_min );
}

```
> 0 votes

---
Tags: collision-detection, physics, collision-resolution
---