title: How To Make Seamless Custom CubeMap?

text:
# Question
Title: How To Make Seamless Custom CubeMap?
I'm currently working on a Three.js project, and I'm aiming to create a seamless cube map. To achieve this, I created six planes and assembled them into a cube. Then, I utilized a shader to generate noise (these are not textures) on the cube's faces.

you can already see the distortion between the cube faces.

I also implemented a process in the shader to undo the transforms for each mesh, which effectively keeps the noise in place, resulting in a cube map-like object as you can see in the first image below.

At first glance, the cube map appears seamless,  but upon closer inspection, slight distortions are visible at the edges. This becomes a bigger issue when I attempt to convert it to a normal map, resulting in poor lighting. Regardless of the method I try, I always end up with seams where the edges of each face of the cube touch.

(front bottom edge and bottom top edge distortion):

zoomed-in look, you can see how to start to converge.

Any guidance or solutions to achieve a truly seamless cube map would be highly appreciated. I've looked through various resources, but I couldn't find a comprehensive explanation or tutorial specifically tailored to creating seamless cube maps in Three.js.

After doing some more research, when you get extremely close to a seam it appears that the meshes never actually touch (I don’t why I was under the assumption they did); they don’t share the same position at each face edge. Despite my efforts to position them as close as possible without overlapping, there remains a tiny space between the meshes, as indicated by the dotted white line.

I believe that the discontinuity is likely caused by the noise function lacking the necessary additional information to bridge this gap.

It took some time to put together but here is a working example of my code: EXAMPLE

```
let camera,scene,mesh,renderer

//-----------noise functions
function permute(){
  return  `
  vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
  `
 }
function taylorInvSqrt(){
return     `
    vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
    `
}
function snoise(){
return `
      float snoise3D(vec3 v){
        const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
        const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);

        vec3 i  = floor(v + dot(v, C.yyy) );
        vec3 x0 =   v - i + dot(i, C.xxx) ;

        vec3 g = step(x0.yzx, x0.xyz);
        vec3 l = 1.0 - g;
        vec3 i1 = min( g.xyz, l.zxy );
        vec3 i2 = max( g.xyz, l.zxy );

        vec3 x1 = x0 - i1 + 1.0 * C.xxx;
        vec3 x2 = x0 - i2 + 2.0 * C.xxx;
        vec3 x3 = x0 - 1. + 3.0 * C.xxx;

        i = mod(i, 289.0 );
        vec4 p = permute( permute( permute(
                   i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
                 + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
                 + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));

        float n_ = 1.0/7.0;
        vec3  ns = n_ * D.wyz - D.xzx;

        vec4 j = p - 49.0 * floor(p * ns.z *ns.z);

        vec4 x_ = floor(j * ns.z);
        vec4 y_ = floor(j - 7.0 * x_ );

        vec4 x = x_ *ns.x + ns.yyyy;
        vec4 y = y_ *ns.x + ns.yyyy;
        vec4 h = 1.0 - abs(x) - abs(y);

        vec4 b0 = vec4( x.xy, y.xy );
        vec4 b1 = vec4( x.zw, y.zw );

        vec4 s0 = floor(b0)*2.0 + 1.0;
        vec4 s1 = floor(b1)*2.0 + 1.0;
        vec4 sh = -step(h, vec4(0.0));

        vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
        vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;

        vec3 p0 = vec3(a0.xy,h.x);
        vec3 p1 = vec3(a0.zw,h.y);
        vec3 p2 = vec3(a1.xy,h.z);
        vec3 p3 = vec3(a1.zw,h.w);

        vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
        p0 *= norm.x;
        p1 *= norm.y;
        p2 *= norm.z;
        p3 *= norm.w;

        vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
        m = m * m;
        return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
                                      dot(p2,x2), dot(p3,x3) ) );
      }
      `
}

// -------- Create a custom shader
const vertexShader = `
varying vec4 worldPosition;
uniform  int ignoreFront; //<---- this is just a flag to ignore calling the undoTransfroms function for the front face
uniform  mat4 rm;
uniform  vec3 undoPoition;

vec3 undoTransfroms(vec3 v, mat4 rm){
  vec4 j =  (rm*vec4(v,1.));
  j.z += undoPoition.z;
  j.y += undoPoition.y;
  j.x += undoPoition.x;
  return j.xyz;
}

void main() {
    worldPosition = modelMatrix * vec4(position, 1.0);
    vec3 newPosition = position;
    if(ignoreFront == 1){
      newPosition = undoTransfroms( position,  rm);
    }
    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);

}
`;

const fragmentShader = `
uniform vec3 center;
varying vec4 worldPosition;

${taylorInvSqrt()}
${permute()}
${snoise()}

void main() {
    float n = snoise3D(normalize(worldPosition.xyz-center));
    gl_FragColor = vec4(vec3(n), 1.0);
}
`;

//--------build mesh
function createPlaneMesh(x, y, z, rotationX, rotationY, rotationZ, uniforms) {
// Create a plane geometry
const planeGeometry = new THREE.PlaneGeometry(10, 10, 10, 10);
uniforms.center = {value:new THREE.Vector3(0,0,-5)}
const planeMaterial = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
});
// Create the plane mesh
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
// Set the position of the mesh
planeMesh.position.set(x, y, z);
// Set the rotation of the mesh
planeMesh.rotation.set(rotationX, rotationY, rotationZ);
return planeMesh;
}
//------------

function init(){
//-----------Basic setUp
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
document.body.appendChild( renderer.domElement );
renderer.setClearColor( 'white' )

camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 100 );
camera.position.z = 20;
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene = new THREE.Scene();

/********
- set creat mesh
- set transfroms
- set unifroms for undoing of transfoms
*********/
let widthHeight = 10

//------------front
let frontUnifrom = {ignoreFront:{value:0}}
let front = createPlaneMesh(0,0,0,0,0,0,frontUnifrom)
scene.add( front );
//-----------back
let bz    = -widthHeight
let bry   = Math.PI
var undorotationMatrix = new THREE.Matrix4();
undorotationMatrix.makeRotationY(-bry);
let backUnifrom = {rm:{value:undorotationMatrix},undoPoition:{value:new THREE.Vector3(bz*2,0,bz)},ignoreFront:{value:1}}
let back  = createPlaneMesh(0,0,bz,0,bry,0,backUnifrom)
scene.add( back );
//---------right
let rz    = -(widthHeight)/2;
let rx    =  (widthHeight)/2;
let rry   =  Math.PI/2;
var undorotationMatrix = new THREE.Matrix4();
undorotationMatrix.makeRotationY(-rry);
let rightUnifrom = {rm:{value:undorotationMatrix},undoPoition:{value:new THREE.Vector3(-rx,0,-rz)},ignoreFront:{value:1}}
let right = createPlaneMesh(rx,0,rz,0,rry,0,rightUnifrom)
scene.add( right );
//---------left
let lz    =  -(widthHeight)/2;
let lx    =  -(widthHeight)/2;
let lry   =  -Math.PI/2;
var undorotationMatrix = new THREE.Matrix4();
undorotationMatrix.makeRotationY(-lry);
let leftUnifrom = {rm:{value:undorotationMatrix},undoPoition:{value:new THREE.Vector3(-lx,0,-lz)},ignoreFront:{value:1}}
let left  = createPlaneMesh(lx,0,lz,0,lry,0,leftUnifrom)
scene.add( left );
//--------top
let tz    =  -(widthHeight)/2;
let ty    =  (widthHeight)/2;
let trx   =  -Math.PI/2;
var undorotationMatrix = new THREE.Matrix4();
undorotationMatrix.makeRotationX(-trx);
let topUnifrom = {rm:{value:undorotationMatrix},undoPoition:{value:new THREE.Vector3(0,-ty,-tz)},ignoreFront:{value:1}}
let top  = createPlaneMesh(0,ty,tz,trx,0,0,topUnifrom)
scene.add( top );
//---------bottom
let boz   =  -(widthHeight)/2;
let boy   =  -(widthHeight)/2;
let borx  =  Math.PI/2;
var undorotationMatrix = new THREE.Matrix4();
undorotationMatrix.makeRotationX(-borx);
let boUnifrom = {rm:{value:undorotationMatrix},undoPoition:{value:new THREE.Vector3(0,-boy,-boz)},ignoreFront:{value:1}}
let bo    = createPlaneMesh(0,boy,boz,borx,0,0,boUnifrom)
scene.add( bo );
}

// animation
init()

function animation( time ) {
    renderer.render( scene, camera );

}
```

```
 <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
```

# Answer
Firstly, the first derivative discontinuities you observe in your heightmap texture are just an artifact of flattening the spherical/angular domain into six gnomonic projection "charts". Because the projection changes abruptly at the edge of a cube, the gradients have an *apparent* change in direction there too. But once this is re-projected to a sphere, that kink vanishes, as the projection for reading the cubemap exactly cancels out the projection used for writing it. So as long as your ultimate intent is to render this texture on a sphere or otherwise in the angular domain (like a skybox), these projection artifacts are safe to ignore.

As for how to avoid problems when trying to convert this greyscale heightmap into normals, my advice is: *don't*.

**Calculate your normals analytically** as part of evaluating the noise function, rather than trying to infer them later by taking finite differences of the heightmap.

This is cheaper and gives higher-quality normals, and saves you from a world of edge- and corner-case grief in trying to get sample-based values to agree across all the tangent space seams.

You can find examples of how to compute derivatives of a gradient noise field simultaneously as you sample it in this previous answer (for Simplex noise) or in this article from Inigo Quilez.

This will give you the direction in 3D space in which the noise field is getting brighter fastest. Zero-out the radial component to get the rate of change along the sphere's surface at that point. The magnitude tells you the slope of the height function "If you slide one unit (`run`) in this direction, height value increases by `rise = length(gradient)`". Multiply that by your height scale to control the intensity of the normals.

Here's some example code showing how we can use these analytical gradients to compute a normal vector in world space:

```
vec3 sampleDir = normalize(worldPos - center);
vec4 noise = noised(sampleDir); // Using IQ's "noise-with-derivative"

// IQ's version returns noise value in x, gradient in yzw.
float height = noise.x;
vec3 gradient = noise.yzw;

// Zero out component perpendicular to the sphere.
float3 onSphere = gradient - dot(sampleDir, gradient) * sampleDir;

// Normal vector tilts away from "uphill" direction.
float3 normal = normalize(sampleDir - onSphere * heightScale);

```

The advantage of forming this normal in world space is that all adjacent cube faces will agree on the value of the normal where they meet. The downside is that you lose some precision when storing object/world-space normals, you can't compress the texture as easily, and it's harder to blend the result with detail normal maps or scale the intensity of the normals after the fact.

If you prefer to work in tangent space, you can use the TBN matrix at that point of the cube-sphere to transform the world space result into the tangent space for the plane. As long as you use the same tangent space for writing and for reading, you'll get back to the same "net" normal after the fact, and you should still have seamless agreement between adjacent faces. But if you store the normal map in tangent space, don't store/read it as a cubemap (adjacent faces don't always agree about the orientation of the tangent space, causing ugly interpolation where they meet).
> 3 votes

---
Tags: shaders, three.js, cubemap, noise
---


# Question
Title: Problem with JSON ScriptableObject saving using NewtonSoft JSON
I am saving a list of `ScriptableObject`s in a JSON file using NewtonSoft JSON, the problem being that the following error message is thrown when it tries to save:

`NotSupportedException: rigidbody property has been deprecated(wrapper dynamic-method) UnityEngine.GameObject.Getrigidbody(object)`

My code for saving and loading:

```
private static readonly string SaveFileFolder = Application.persistentDataPath + "/Saves/";

    public static void Save(SaveData data)
    {
        if(Directory.Exists(SaveFileFolder) == false)
        {
            Directory.CreateDirectory(SaveFileFolder);
        }

        File.WriteAllText(SaveFileFolder + "Data.sav", JsonConvert.SerializeObject(data));
    }

    public static SaveData Load()
    {
        string _savePath = SaveFileFolder + "Data.sav";

        if(File.Exists(_savePath) == true)
        {
            return(JsonConvert.DeserializeObject<SaveData>(File.ReadAllText(_savePath)));
        }
        else
        {
            Debug.LogWarning("SaveFile could not be found in: " + _savePath);
        }
    }

    [System.Serializable]
    public class SaveData
    {
        [SerializeField] public GlobalGameStatistics.ProgressData ProgressData = new GlobalGameStatistics.ProgressData();
        [SerializeField] public GlobalGameStatistics.StatisticsData StatisticsData = new GlobalGameStatistics.StatisticsData();

        public SaveData(SaveData data)
        {
            ProgressData = data.ProgressData;
            StatisticsData = data.StatisticsData;
        }

        public SaveData(GlobalGameStatistics.ProgressData progress, GlobalGameStatistics.StatisticsData statistics)
        {
            ProgressData = progress;
            StatisticsData = statistics;
        }
    }

```

The ScriptableObject I'm trying to save:

```
[CreateAssetMenu(fileName="MissionTemplate", menuName="Game/Mission Template"), Serializable]
public class MissionTemplate : ScriptableObject
{
    [Header("Settings:")]
    public float time;
    public MapTemplate map;
    public PopulationTemplate population;
    public TargetTemplate target;
    public StoryMessage[] messages;

    #region Classes

    [Serializable]
    public class StoryMessage
    {
        [HorizontalGroup("Header")]
        public string headline;
        [HorizontalGroup("Header")]
        public string sender;
        [TextArea(8, 8)] public string text;
        [HideInInspector] public bool read;
    }

    #endregion
}

```

The `GlobalGameStatistics.Progress` class is where a list of `MissionTemplate`s is contained which should be saved.

# Answer
> 0 votes
Here's what I use (swap in JSON for binary serialization if you really must):

```
public static class DataStorage
{
    static readonly string Data_Extension = ".GameData";

    public static string Save<T>(T obj, string savePath, string key)
    {
        string path = Path.Combine(Application.persistentDataPath, savePath);
        Directory.CreateDirectory(path);
        path = Path.Combine(path, $"{key}{Data_Extension}");
        File.Delete(path);

        Debug.Log($"Saving: {path}");
        using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate)) // Overwrite
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, obj);
        }

        return path; // this is here for test automation and/or debugging help
    }

    public static T Load<T>(string savePath, string key)
    {
        string path = Path.Combine(Application.persistentDataPath, savePath, $"{key}{Data_Extension}");
        T loadObject = default;
        if (!File.Exists(path)) return loadObject;

        Debug.Log($"Loading: {path}");
        using (FileStream stream = new FileStream(path, FileMode.Open))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            loadObject = (T) formatter.Deserialize(stream);
        }

        return loadObject;
    }
}

```

The data and ScriptableObject:

```
public class GameStateData
{
    public GameSource GameSource;
    public States State;
    public Vector3Int PlayerMapLocation;
}

public class GameStateSO : ScriptableObject
{
    public GameStateData Data = new GameStateData();
}

```

Then I call it with:

```
DataStorage.Save(gameStateSO.Data, savePath, "GameStateSO");

gameStateSO.Data = DataStorage.Load<GameStateData>(savePath, "GameStateSO");

```

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


# Question
Title: Third Person Character Fall through the floor
i'm trying to get my main menu level works... but when i play from the main menu and go into the "Game"scene player will fall down throught the floor, but won't if i play directly from the "game"scene... what i'm doing wrong? i'm using UGAmePlaystatistics::OpenLevel() to change level from Main menu to Game level..and i didn't touch any of the value inside the third person character.. any help?

https://www.youtube.com/watch?v=MpIYgzOaBt8

# Answer
> 1 votes
My guess would be that the player pawn/actor is created before the floor and thus falls through just enough so that when the floor is created it can fall completely though. To test this theory you could move the spawnpoint of the player just a little bit up or only enable gravity simulation when the whole scene is loaded

If this doesn't work, perhaps you can post a screenshot of the configuration of the player and of the floor in the inspector so other people can more easily reproduce this problem.

# Answer
> 0 votes
When using `UGameplayStatics::OpenLevel` to start a new level, the physics assets might not be loaded immediately. This is because OpenLevel both opens and starts the level, including loading assets, at the same time.

To address this issue and ensure that all necessary assets are loaded before starting the new level, you can use the `UGameplayStatics::LoadStreamLevel` function first, followed by `UGameplayStatics::OpenLevel` **when the Level is ready**.

The LoadStreamLevel function asynchronously loads the specified level in the background, allowing assets to be loaded while your game continues running. Once the assets are ready, you can then use OpenLevel to actually start the level.

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


# Question
Title: Testing for creating Party Member Scenes continuously - Able to create multiple but after the first is custom type is not determined
For my quick test to see if I can create multiple combatants for my battles, I would like to be able to continuous create party members/enemies in order to get to the correct amount of combatants expected (the total amount).

The debugger is showing the root scene children to be:

```
Running Applications... Party Member<ID:Area2D> ... @Area2D@6#ID

```

where the expected output should be:

```
Running Applications... Party Member<ID:Area2D> ... Party Member<ID:Area2D>

```

and so on, including the enemy types as well

So it looks like it is reverting back to the Area2D, rather than staying as the Party Member class custom object.

I have followed many different ways of creating the new instances but none are working as expected. I was able to test quite a lot up until now where I need to be able to access the object properly in order to determine what type it is and call the expected function, etc.

```

func createPartyMemberObject(root, job):

    partyPath = load("res://Resources/Party Members/Party Member.tscn")

    var party = partyPath.instantiate()
    party.resource = job

    print_debug(party)

    root.add_child(party)

    print_debug(party)

    return party

```

In fact it seems to keep the Party Member class up until it is ready to be added to the root path. So it keeps the class name until after adding the child into the scene root (add\_child). - I'm not sure if there is something that I am missing here.

For the first instance it continues as expected, but from the second instance on it isn't working properly.

I have tried creating multiple different variables in order to track the different party members but that didn't work either.

Possibly it has something to do with the partyPath, but I'm not sure what it could be. maybe the instantiate only works for the one object rather than multiple. Commenting out the load var and keeping at a higher level, etc. didn't work.

I couldn't find any bugs in godot github, so I'm not sure if it is a bug or something that I am missing.

Thank you in advance for any help.

# Answer
Try statically typing your vars (and `func` return value), like this:

```
var party_scene := preload("res://Resources/Party Members/Party Member.tscn")

func createPartyMemberObject(root, job) -> PartyMember:
  var party: PartyMember = party_scene.instantiate()
  ...

```

Source.
> 1 votes

---
Tags: gdscript, godot-4
---


# Question
Title: Is an ECS system without a traditional ECS memory layout a bad idea?
I've got a background in C++ but completely new to game dev, Unreal, and ECS.

Recently, I learned about ECS and fell in love with the resulting project structure and theoretical reduction of spaghetti code that could arise as a game project grows. However, Unreal (or most other mainstream engines) have limited or no ECS systems ready to go. As a result, I decided to try to implement what I like to call a *Pseudo-ECS* on my own within an Unreal project that lets Unreal handle basics like rendering and physics, and the *Pseudo-ECS* will handle all gameplay logic.

It's *similar* to a true ECS system in terms of separation of data and logic, however it **does not** follow the ECS memory layout, entity id lookups, or even querying for that matter. Here's how it's set up:

---

All components/systems are derived from these 2 `ActorComponent` classes and live in their respective folders:

When an `ECS_Component` is added/removed from an actor in the world, that actor is stored in a global queue for the next frame to process.

Every tick, the global queue is processed against a list of registered `ECS_Systems` and then cleared. Essentially, `ApplySystems` will be called on every actor that had a change to the `ECS_Components` that were applied to it.

`ApplySystems` checks the required `ECS_Components` for each `ECS_System` (using a set of 4 int64 bitflags & bitmasks, supporting up to 255 components) and if the actor has those components, then that `ECS_System` is added/removed from it.

The function is a bit too big to post here. Basically, it loops through all the components on the actor and generates a bitflagged set of int64's. Then it loops through every system in the game and checks via bitmask to see if the actor should use the system.

---

The result; all system logic only runs on actors that have the required components. When a component is added/removed, the actor gets updated to ensure it has the right systems at all times. And this works! I successfully created basic health, hunger, and follow systems with this.

Here's the thing... obviously, I would be missing out on any performance gains from a **true** ECS system, however performance is not what drew me to ECS in the first place. That being said, I don't want this system to be a hindrance to the games performance either.

My question is, do you think this *Pseudo-ECS* system is worth using even without a true ECS memory layout or querying system? I really have no frame of reference to know this...

# Answer
> 0 votes
The way I see it, Unreal and Unity are large codebases of licensable engines. And it large toolchain and asset pipeline. The problem is they add a ECS to it which is large refactoring effort and taking in to account how the best iterative implement ECS into it. It is example of how the refactor a finished game engine to ECS which is large undertake. To understand the concept of ECS. Best thing in my opinion would be to dive in the theory. The book Data oriented design? Richard Fabian. Also C++ specific. If your C++ are of high level OOP you would see OO solutions to every ECS problem. C++ multi-paradigm. So I would delve deeper into C++ Functional paradigm support.

Then the biggest mistake is ECS isn’t particle system it is extreme overkill to authentic Pong game. ECS shine wen you have large amount of different game objects. So the benefit arise at often much larger scope of game. From Phong to arena shooter no. A Arma large scale milsim, Homeworld , xseries. Starcitizen. My opinion only then you experience the benefit of pure data oriented entity component system. To me encapsulation in ECS DOD is at level of the systems. Where the logic and data is isolated. And is decoupled.

To me a good example to research ECS to make a 2D game using carrier fleet warfare or Mainbattle tank and armored infantry in WW II setting you have a halftrack truck which is for OOP diamond of dead game object.

A pong game even C++ is overkill I would choose web game in HTML5 Canvas game. With intermediate complex games you get benefit in OOP if you shift from inheritance to component game objects. Often that refactoring within OOP is for most game enough benefit. For asset control and data driven. Asset pipeline your asset tool would be database in it core if you gp full pure dod ECS.
Using Unreal you are bound by their implementation of a ECS. And the type of games it supports. And then it is choice if that suit you game project often it does.

# Answer
> 0 votes
To start off with, there's no requirement that an ECS needs to adhere to Data-Oriented Design principles. ECS has been around forever (I was working on games with them over 20 years ago, and yes we even called them entity components), just they're also a really good fit for DoD. Likewise, you can implement DoD principles without an ECS (ECS is just one aspect of a pure/full DoD implementation, and you don't need to have a pure implementation to reap many of its benefits).

However, there are a couple of glaring problems with your approach of considering components as data and systems as dependent on specific combinations of components.

> Basically, it loops through all the components on the actor and generates a bitflagged set of int64's. Then it loops through every system in the game and checks via bitmask to see if the actor should use the system.

Firstly, how will you handle cases where there can be more than one instance of a data type? e.g. wheels, ammo, etc. If each data type has a specific slot (bit in your bitmask), you're going to need different data types for each wheel (front/back for a motor bike, fl/fr/rl/rr for a regular car, fl/fr/??/??/rl/rr for a 6 wheeler semi, etc.) or ammo type (9mm, 50mm, etc.). If you do have a single data type for such things, how will you know what slot they're meant to go in? This is a pretty big design limitation.

Secondly, if your systems are automagically used based on the components present, you will be further constrained to creating excessive component/slots for every specialization and redundant systems too, and that will limit the ability for game design to share resources. Take for instance a few different weapons, which for the games design you want to all draw from a single ammo type - how will that be achieved, if adding an 'energy ammo' component automatically adds all compatible weapon systems? Which system is used to process the component? Similarly for the wheel case, will you now need to have separate systems for each vehicle type, even though a wheel's a wheel? You're now polluting your ECS systems with checks that an ECS system is meant to avoid.

There are of course solutions to these issues, but I believe they're an indicator that you haven't selected the right approach to your ECS implementation.

---
Tags: performance, unreal-4, entity-component-system
---


# Question
Title: How to use WASD to move camera between a collection of position marker objects?
How can I move one camera between two positions along the cardinal directions?

Using W/A/S/D keys, I want to move the camera from one empty object to another on the xy plane. Those empty objects would act like destination points for the single camera object.

I don't want to assign a unique key for each destination point, so instead the W key should always go to the next object to the left, etc.

When a directional key is pressed, the camera should move to the closest marker point in that direction. There can be many of these points, arranged somewhat like a grid, but the spacing is not guaranteed to be equal.

# Answer
> 0 votes
Try something along the lines of this:

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

public class CameraMover : MonoBehaviour
{
    public struct TransformRow {
          [SerializeField] public Transform[] row;
    }

    [SerializeField] private List<TransformRow> grid = new List<TransformRow>(); //Set this up in editor
    private Vector2Int gridPosition = new Vector2Int(0, 0);
    [SerializeField] private Camera camera;

    public Transform GetTransformAtPosition(Vector2Int position)
    {
        return grid[position.x].row[position.y];
    }

    private void Update()
    {
        //Put your movement code here. Adjust it so it changes gridPosition, but only once and only by one when the key is first pressed.
        camera.transform.position = GetTransformAtPosition(gridPosition).position;
    }
}

```

Essentially, you’re just chucking all the empty game objects that act as the points for the camera to warp to into what is essentially a 2D array, which creates the lattice you want. Then you just have to add the code to teleport the camera to the empty game object :).

Ideally you would want to refactor some parts of this code to better fit your purpose. This code is definitely not optimised nor solid, but I trust you’ll be able to optimise this solution.

---
Tags: unity, c#, movement, input
---


# Question
Title: Why doesn't RectTransform.GetWorldCorners() employ any camera?
Typically, conversion methods from world to screen coordinates and vice versa use a camera to perform these calculations, so I'm wondering how does `GetWorldCorners` method manage without a camera?

---

The second related question concerns the decompiled version of `RectTransformUtility.WorldToScreenPoint` method:

```
public static Vector2 WorldToScreenPoint(Camera cam, Vector3 worldPoint)
{
    if (cam == null)
    {
        return new Vector2(worldPoint.x, worldPoint.y);
    }

    return cam.WorldToScreenPoint(worldPoint);
}

```

Why does it return the same vector if the camera is null?

# Answer
In general, when you have two questions, you should post each one separately. But since these are easy, I'll knock them out together.

---

**First: why does `GetWorldCorners()` not require a camera?**

> Typically, conversion methods from world to screen coordinates and vice versa use a camera to perform these calculations

That's true. but `GetWorldCorners` is *not* a conversion method that maps between world and screen coordinates, so that does not apply here.

Let's look at what the docs say about this method:

> `public void GetWorldCorners(Vector3[] fourCornersArray);`
>
> **Description**
> Get the corners of the calculated rectangle in world space.
>
> Each corner provides its world space value. The returned array of 4 vertices is clockwise. It starts bottom left and rotates to top left, then top right, and finally bottom right. Note that bottom left, for example, is an (x, y, z) vector with x being left and y being bottom.

Note that the words "screen" or "camera" appear nowhere here. This method has nothing to do with *any* camera's *view* of a `RectTransform`. It just tells you where the corners of that rectangle object are in the world coordinate system of your game - the coordinate system that your cameras *look at* as input, not the screen space coordinates they transform content *into*.

It's like asking "Why doesn't Google Maps need to know the shape of my camera lens to tell me the latitude and longitude of a landmark?" - the landmark just is where it is, no matter how you look at it.

Words like "left" and "bottom" here should be interpreted in reference to the `RectTransform`'s local coordinate system. You could have three different cameras looking at the same canvas - one right-side-up, one on its side, and one upside-down, so they'd disagree about which corner is the "bottom left". We use the `RectTransform`'s own coordinate space as the canonical ordering, so we get an unambiguous answer, no matter how the transform has been rotated/scaled/etc.

---

**Second: why does `WorldToScreenPoint` return the input vector unchanged if the camera is null?**

The only case in which it makes sense to get the screen position of a point in a `RectTransform` without a camera is if the canvas is in "Screenspace - Overlay" mode. In that mode, the world space coordinates within the canvas map 1:1 with pixel coordinates on the screen, so there's no conversion needed - just truncate off the z coordinate, and the remaining x and y are already pixel positions in screen space.

In the other canvas modes, "Screenspace - Camera" and "Worldspace", the position where a point ends up on the screen depends on the camera settings, so in those cases it's not valid to pass `null` in place of the camera.
> 0 votes

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


title: Using both look_at and flip_h in Godot

text:
# Question
Title: Using both look_at and flip_h in Godot
I am trying to have a player running in a side scroller platformer with its arms independent from its body, so that the arms can follow the mouse (to aim).

The issue is that when the character goes to the left I use `flip_h` to flim it and its arm, which makes `look_at()` obviously not work properly. But I'm not sure how to go about fixing it since we can't just invert the rotation angle of the arm because its values do not make sense to me (they are incremented very slowly and are not comprised between 0 and 360).

GitHub project to demonstrate the issue

Player script

```
extends CharacterBody2D

const SPEED = 300.0
const JUMP_VELOCITY = -400.0

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

@onready var animator = get_node("AnimatedSprite2D")
@onready var arm = get_node("Arm")

func _ready():
    animator.play("Run")

func _physics_process(delta):
    # Add the gravity.
    if not is_on_floor():
        velocity.y += gravity * delta

    # Handle Jump.
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    # Get the input direction and handle the movement/deceleration.
    # As good practice, you should replace UI actions with custom gameplay actions.
    var direction = Input.get_axis("ui_left", "ui_right")
    if direction == 1:
        animator.flip_h = false
        arm.flip_h = false
    elif direction == -1:
        animator.flip_h = true
        arm.flip_h = true
    if direction:
        velocity.x = direction * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)

    move_and_slide()

```

Arm script

```
extends Sprite2D

# Called when the node enters the scene tree for the first time.
func _ready():
    pass # Replace with function body.

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    print(rotation)
    print(flip_h)
    # rotation = get_global_mouse_position().angle_to_point(position)
    var mouse_pos = get_global_mouse_position()
    look_at(mouse_pos)

```

# Answer
> 2 votes
`flip_h` is making your arm point in the "opposite" direction when you use `look_at`. A quick, simple solution would be to look at the "opposite" point when facing left, that is, `look_at` the mouse location flipped across your character:

```
func _process(delta):
    var mouse_pos = get_global_mouse_position()
    if flip_h:
        mouse_pos = Vector2(global_position + (global_position - mouse_pos))
    look_at(mouse_pos)

```

---
Tags: rotation, godot, angles
---


# Question
Title: GameObjects loaded from OBJ files have inherent position offsets; any way to measure these in worldspace?
I have OBJ files that I'm loading into my scene at runtime. They all have positions offset from zero.

These positions appear to be inherent to the .obj file as they were set in the 3D modelling program that they were exported (from Rhino).

Unity seems blind to these offsets: if I upload all .obj's to Unity's worldspace position 0,0,0, they'll each be positioned differently based on their inherent offsets but Unity only seems to understand their positions being at 0,0,0.

Is there any way to calculare the distances between these objects in Unity, in this case?

I need both the objects to have their offsets from the modelling software but I also need to measure the distance between them.

# Answer
The "position" of an object is the location of the (0,0,0) point in the object's local "object space" coordinate system — the local origin.

If the mesh has been exported so that all its vertices are located somewhere away from (0,0,0), then you'll see this effect where the visible part of the object is offset from what the engine thinks of as its position. Those offsets are just part of the positions of each vertex, measured from the local origin — there's no intermediate layer of hierarchy between object space and the mesh within object space that stores where the nesh "really is". Each vertex is allowed to tell a different story here.

So you can't really recover where the mesh is "supposed" to be relative to the local origin. Any point is as valid a candidate as any other, and picking a good one requires some human interpretation. Common choices might be taking the centroid of all the vertices, the center of an axis aligned bounding box, etc., but some objects will need this point hand-placed at a structural feature that sits-off center.

What you can do is re-export your objects so their local origins are where you want them to be within the visible mesh, then place them inside container objects, offset from the container by the displacement you need to put the mesh in the right place in your scene. That level of hierarchy will let you get two special points: the spawn point in the world (origin of the top/container level) and the object's logical position for measurement purposes (origin of the bottom/mesh object level).

If keeping your export as-is is important, then you can reverse this, and hand-place a marker object as a child of each mesh, positioning it where you want to measure their positions from, relative to their visible mesh. When you want to do your measurements, take the world space positions of these marker objects as your inputs, rather than the positions of the mesh objects themselves with their offset origins.
> 1 votes

---
Tags: unity, obj, position
---


# Question
Title: Perspective projection not working as intended
I copied a perspective projection matrix from here (https://jsantell.com/3d-projection/) and applied it to my vertices. It looks ok but without depth. Rotation matrices also work.

When I try to divide all components by the w-component after applying the projection matrix I get some weird geometry. This is what I have understand should be done to apply depth projection.

Below is my code, I'm using python and pygame for drawing the polygons of a cube.

What the cube looks like if I don't divide by w:

With division:

import pygame
import math
import copy

pygame.init()

screen_width = 960
screen_height = 800
screen = pygame.display.set_mode([screen_width, screen_height])
clock = pygame.time.Clock()
FPS = 60
run = True

class Renderer():
    def __init__(self):

        self.cube = [
        [[0, 0, 0, 1],    [0, 1, 0, 1],    [1, 1, 0, 1]],
        [[0, 0, 0, 1],    [1, 1, 0, 1],    [1, 0, 0, 1]],
        [[1, 0, 0, 1],    [1, 1, 0, 1],    [1, 1, 1, 1]],
        [[1, 0, 0, 1],    [1, 1, 1, 1],    [1, 0, 1, 1]],
        [[1, 0, 1, 1],    [1, 1, 1, 1],    [0, 1, 1, 1]],
        [[1, 0, 1, 1],    [0, 1, 1, 1],    [0, 0, 1, 1]],
        [[0, 0, 1, 1],    [0, 1, 1, 1],    [0, 1, 0, 1]],
        [[0, 0, 1, 1],    [0, 1, 0, 1],    [0, 0, 0, 1]],
        [[0, 1, 0, 1],    [0, 1, 1, 1],    [1, 1, 1, 1]],
        [[0, 1, 0, 1],    [1, 1, 1, 1],    [1, 1, 0, 1]],
        [[1, 0, 1, 1],    [0, 0, 1, 1],    [0, 0, 0, 1]],
        [[1, 0, 1, 1],    [0, 0, 0, 1],    [1, 0, 0, 1]]]

        for tri in self.cube:
            for point in tri:
                point[0] -= 0.5; point[1] -= 0.5; point[2] -= 0.5

        a = screen_height/screen_height
        n = 1
        f = 1000
        t = n * math.tan(math.radians(90/2))
        b = -t
        r = a * t
        l = -r

        self.projection = [
            [(2*n)/(r-l), 0, (r+l)/(r-l), 0],
            [0, (2*n)/(t-b), (t+b)/(t-b), 0],
            [0, 0, (f+n)/(n-f), (2*f*n)/(n-f)],
            [0, 0, -1, 0]
        ]

        self.rot = 0
        self.update_roty()

    def update_roty(self):
        self.rotation_y = [
            [math.cos(self.rot), 0, -math.sin(self.rot), 0],
            [0, 1, 0, 0],
            [math.sin(self.rot), 0, math.cos(self.rot), 0],
            [0, 0, 0, 1]]

    def Matrix_MultiplyVector(self, i, m):

        vx = i[0] * m[0][0] + i[1] * m[0][1] + i[2] * m[0][2] + m[0][3]
        vy = i[0] * m[1][0] + i[1] * m[1][1] + i[2] * m[1][2] + m[1][3]
        vz = i[0] * m[2][0] + i[1] * m[2][1] + i[2] * m[2][2] + m[2][3]
        vw = i[0] * m[3][0] + i[1] * m[3][1] + i[2] * m[3][2] + m[3][3]

        vx /= vw
        vy /= vw
        vz /= vw
        vw /= vw

        return [vx,vy,vz,vw]

    def draw(self):

        self.rot += 0.0175
        self.update_rotx()
        self.update_roty()
        self.update_rotz()

        a = screen_height/2

        for tri in self.cube:

            tricopy = copy.deepcopy(tri)
            proj_points = []

            for i, point in enumerate(tricopy):

                tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_y)
                tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.projection)

                tricopy[i][0] *= 50; tricopy[i][0] += a
                tricopy[i][1] *= 50; tricopy[i][1] += a

                proj_points.append((tricopy[i][0], tricopy[i][1]))

            pygame.draw.polygon(screen, [230,168,50], proj_points, 1)

renderer = Renderer()

while run:

    screen.fill([47,79,83])
    mx, my = pygame.mouse.get_pos()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()

    keys = pygame.key.get_pressed()
    renderer.user_input(keys)

    renderer.draw()

    clock.tick(FPS)
    pygame.display.flip()

pygame.quit()```

# Answer
Apparently it was a problem of the cube being "inside" the "camera".

I tried before to add += 3 to the z-axis of every triangle but it didn't work. Then I noticed it could only be added **after** the rotation matrix had been applied for some reason, but **before** the projection matrix.
> 0 votes

---
Tags: 3d, graphics, python, pygame, projection
---


# Question
Title: How can I make this Worley noise generator more efficient?
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class worley : MonoBehaviour{
public Material mate;
int size = 1000;
int subdiv = 4;

float mindist(Vector2[] vecarr, Vector2 pointe){
    float mindis = 1;
    for (int i = 0; i < vecarr.Length; i++){
        float dist = Vector2.Distance(vecarr[i], pointe) / size;
        mindis = Mathf.Min(dist, mindis);
    }

    return mindis;
}

Texture2D worley(Texture2D textu, int sizee, int subdivi){
    Vector2[] pointss = new Vector2[subdivi * subdivi];

    for (int i = 0; i < subdivi * subdivi; i++){
        pointss[i] = new Vector2(Random.Range(0, 1000), Random.Range(0, 1000));
    }

    for (int x = 0; x < sizee; x++){
        for (int y = 0; y < sizee; y++){
            float md = mindist(pointss, new Vector2(x, y));
            textu.SetPixel(x, y, new Color(md,md,md,1f));
        }
    }
    textu.Apply();
    return textu;
}

void Start(){
    Texture2D tex = worley(new Texture2D(size, size), size, subdiv);
    mate.SetTexture("_MainTex", tex);
}
}

```

# Answer
> 3 votes
In computer science parlance, the work you're doing in this code is called "embarrassingly parallel". You're doing the same calculation for a million pixels, and each of those million results does not depend on knowing the results from another one.

So the best way to make this efficient is to move it off the CPU entirely. Rather than computing those million results one at a time, throw it at the GPU what can run waves of them in parallel! This not only cuts down on start-to-finish processing latency, but it keeps all the texture memory writing GPU-side, so you're not bottlenecked by shunting that data across the memory bus.

We can make this type of noise efficient enough that it can be sampled on-demand in a shader in many applications, rather than writing it out to a texture to be read back in (which costs memory and texture sampling bandwidth and loses precision to quantization).

Here's a quick Unity shader implementation, based on some of Inigo Quilez's published examples. (His articles also show how to achieve some extra bells and whistles like smooth blending between Voronoi cells or distance functions from the closest edge)

```
Shader "Unlit/Worley" {
    Properties {
        _Density ("Density", float) = 8
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float _Density;

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv * _Density;
                return o;
            }

            // 2-component hash function borrowed from Inigo Quilez's
            // "Voronoi - smooth" ShaderToy demo:
            // https://www.shadertoy.com/view/ldB3zc
            float2 hash2(float2  p ) {
                p = float2( dot(p, float2(127.1f, 311.7f)),
                            dot(p, float2(269.5f, 183.3f)));
                return frac(sin(p)*43758.5453f);
            }

            float worley(float2 p) {
                // Which integer grid cell are we in?
                float2 cell = floor(p);
                // Where are we within that cell [0-1)?
                float2 inCell = p - cell;

                // Farthest a point can be from closest seed point
                // is one square diagonal, which is sqrt(2) away.
                float smallestSquared = 2.0f;
                // Iterate over the 3x3 block of nearby grid cells.
                for(int x = -1; x <= 1; x++) {
                    for (int y = -1; y <= 1; y++) {
                        // Compute the position of the seed point in that cell
                        // relative to this cell.
                        float2 shift = float2(x, y);
                        float2 seed = hash2(cell + shift) + shift;

                        // Compute distance from sample point to the seed point.
                        float2 sampleToSeed = seed - inCell;
                        float squaredDistance = dot(sampleToSeed, sampleToSeed);

                        // Keep the smallest squared distance.
                        smallestSquared = min(smallestSquared,
                                              squaredDistance);
                    }
                }

                // Normalize so farthest possible distance is 1,
                // and square root to get linear length.
                return sqrt(smallestSquared/2.0f);
            }

            fixed4 frag (v2f i) : SV_Target {
                return float4(worley(i.uv).xxx, 1.0f);
            }
            ENDCG
        }
    }
}

```

The basic idea here is to divide our domain into some number of grid cells - controlled by the `_Density` parameter in this shader. In each grid cell, we'll pseudo-randomly scatter a seed point, using the `hash2` function so that we always get the *same* pseudo-random point for a given grid cell. To sample the Worley noise, we just need to check the seed point in the grid cell containing our sample point, and the 8 neighbouring grid cells (since a sample on the edge of a grid cell might be farther from the seed point in its own cell than it is from the point in the neighbouring cell).

This gives you a wonderful scaling property: it costs the same amount of work to render `width` x `height` pixels of Worley noise containing 1 seed point as it does to render that same `width` x `height` pixels' worth with a million seed points! No matter how many seeds you have in total, each pixel only needs to peek at 9 of them. Try cranking up the `_Density` to a ridiculous value and notice the material still renders in real time.

Because of this, as I alluded earlier, you might not need to write this noise to a texture at all. You may find it's cheap enough to just call the `worley()` function with your sample coordinates instead. But if you do want to write this to a texture, you can create a `RenderTexture` and stamp a material using this shader into it with `Graphics.Blit()`.

---

If you want to keep this work CPU-side, there are some simple best-practice improvements you can make for a modest speed-up, without radically altering your approach.

* Don't set pixels one at a time. Make a CPU-side array to store all your new colour values, then set them all at once.
* When trying to find the smallest distance in a collection, you can defer the square root part of the computation until the end. (if \\$0 \le x \< y\\$, then \\$x^2 \< y^2\\$ so you still get the correct minimum while saving an expensive transcendental computation)
* When dividing millions of points by the same constant, it's faster to calculate the reciprocal once and multiply by it.

With those adjustments, your inner loop looks more like this:

```
static float MinDistance(Vector2[] seeds, Vector2 sample) {
    // Start the loop with the first distance, so we call Min() one time fewer.
    float minSquared = (seeds[0] - sample).sqrMagnitude;
    for (int i = 1; i < seeds.Length; i++) {
        minSquared = Mathf.Min(minSquared, (seeds[i] - sample).sqrMagnitude);
    }
    // Perform the expensive square root only once, on the distance we want to keep.
    return Mathf.Sqrt(minSquared);
}

// ...then later, in your texture-filling routine...

   // Make our CPU-side staging buffer (borrow some temp memory we can release later).
   var staging = System.Buffers.ArrayPool<Color32>.Shared.Rent(size * size);

   // Constant conversion factor from pixel distance to 0-255 brightness.
   float distanceScale = 255f/size;

   int texelIndex = 0;
   for (int x = 0; x < size; x++){
        for (int y = 0; y < size; y++){
            float md = MinDistance(points, new Vector2(x, y));

            // Perform conversion once, rather than once per channel.
            byte value = (byte)Mathf.RoundToInt(Mathf.Min(md * distanceScale, 255));
            // Using Color32 is cheaper than Color when we don't need float precision.
            staging[texelIndex++] = new Color32(value, value, value, 255);
        }
    }

    // Write the textures all at once.
    texture.SetPixels32(staging);

    // Recycle the temporary array we rented.
    System.Buffers.ArrayPool<Color32>.Shared.Return(staging);

    texture.Apply();

```

The next stage beyond this would be to not check every seed point for every pixel. A pixel in the bottom-left of the texture probably doesn't need to check a seed point in the top-right - something else will almost certainly be closer. You can arrange your points into a spatial partition so each pixel only has to visit a few of them. We used a version of that trick in the shader approach, ensuring each pixel only had to look at the seeds in the 9 closest grid cells.

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


# Question
Title: How to deal with mismatch between fps and monitor refresh rate?
Say I have a game running at some number of frames per second on a 60 Hz monitor. I would like to display my frames correctly in the sense that the in-game time difference between two consecutive displayed frames remains constant (e.g. 1/60 seconds). Now the allowed frame rates are 30, 60, 120 etc., and an obvious solution would be to enable vsync. However, with vsync enabled, the delta times are not exact multiples of 1/60 seconds, which means that I can't technically use them if I want the correct frame sequence. Instead, I would need to make the code explicitly dependent on the refresh rate. Is this even something to worry about, or should I just trust that the delta times are *close enough*? What if I use uncapped fps and the fps is *high enough*, should I then worry about fluctuations in elapsed in-game times between monitor refreshes?

# Answer
> However, with vsync enabled, the delta times are not exact multiples of 1/60 seconds, which means that I can't technically use them if I want the correct frame sequence.

It's not entirely clear what your concern is here. Generally, we don't care what the monitor refresh rate is - we care how many frames per second are *actually getting rendered*. This could be higher or lower than the monitor refresh rate depending on the game's graphics settings, the player's hardware, and the player's driver settings.

There are two ways to approach the speed/timing of motion and other gameplay mechanics:

* **Frame updates**: Using this approach, we update the game state once each time a frame is rendered. To ensure that the motion remains smooth even when the gamplay is changing, we scale the motion for each frame based on how much real time has elapsed since the previous frame. Motion will generally look smoother on a wider range of devices. CPU usage will be lower on low-end devices (because fewer frames are rendered per second, we perform fewer updates) and higher on high-end devices (the inverse). Things can sometimes break if the framerate gets extremely low and you are performing so few updates per second that motion is extremely imprecise.
* **Fixed updates**: With fixed updates, we update the game state at a constant interval (such as 60hz) regardless of how many frames per second are being rendered. Although we could used fixed hardcoded values for things like speed and timing, it's best to scale the motion based on the fixed update rate (number of updates per second) so that we can easily change the fixed update rate in the future without having to change all of the speed/timing values in our game. CPU usage will be more consistent/less dependent on framerate. Motion will likely be more precise on low-end hardware where the framerate is low. However, you might get complaints from users with high-end hardware - for example, a user with a 240hz monitor might complain if they notice the camera is rendering at 240hz but objects are only moving at 60 hz.

**Update** @bananab0y, in response to your comments on this answer: you are thinking about this the wrong way. It is not "incorrect" to render 90 fps while the user only sees 60fps. You are thinking about rendered frames as if they are units of time, but that is not the case. The timing of our important gameplay mechanics should be *independent of framerate*. **In other words, we don't say that the cooldown for an attack should be 30 frames or that a character should move .1 unit per frame. We say that the cooldown of an attack is a half-second or that a character should move 6 units per second.** Each rendered frame simply shows the game state at a particular moment in time, just like how each frame of a movie shows what was happening in front of the camera at a particular moment in time.

Let's look at this a different way. Imagine we record 10 seconds of gameplay to a video file with a framerate of 60 frames per second. When we watch the video file, we see exactly what happened. Now, we reduce the framerate of the video file to 30fps and skip every other frame. Is this new 30fps video "incorrect"? The new video is still 10 seconds long and shows the same events over the same time period. It doesn't change what actually happened, or the speed at which it happened - it just changes how smooth the motion looks.
> 0 votes

# Answer
There's only two important times for developers to stress about their frame rate vs monitor refresh rate. When the *assets* you have are meant to render at a certain rate (16fps sprites vs 60hz monitor, or 30fps sprite vs a 144hz monitor). And when your *game* runs slower and non integer ratio to the refresh rate of the monitor.

Your question and further responses are confused, hinting this is an X Y problem, it doesn't appear you have the first two problems. While update rate problems are adresssed by the gaffer on games article, *display rate* is fixed via frame capping, vertical sync, and *monitor hardware variable refresh rate*. But if you *expect* players to not be able to run the game well within minimum requirements and settings, **that's a performance bug in your game**. Hitching, inconsistent frame rates, these are things for you to *fix* not just "work around".

If your concern are frame rates that exceed refresh rates, the typical solution is for the user to use frame rate limiting slightly below the monitors refresh rate (141 for 144hz) on combination with hardware variable refresh rate (gsync/freesync), and force *vsync* on top of that. The minute frame differences are eliminated, and high refresh rates appear smooth under this regime. Further latency can be mitigated with vendor specific technology (Nvidia reflex for example).

This process of figuring out the right settings is largely a process the *user* toys with, not *you* (and might be done via forced settings in their gpu vendors display settings). You just need to make sure the standard list of features are available to **toggle both on and off** in your game (frame cap, vsync, and possibly vendor specific latency tech). If you can't toggle these on and off, you have a bug in your game. If your game doesn't work with these features toggled on and off you have a bug in your game. If your game doesn't work with forced settings, it's a bug in your game.

Most popular engines do not have problems with these settings, and these ideas even appear inmlow level modern graphics APIs, so it's unlikely to be something the average developer needs to deal with specificically.
> 0 votes

---
Tags: game-loop, frame-rate
---


# Question
Title: What interchange format should I use for e.g. subtitles and UI texts?
Are there any standard formats that can be used as the source material for game texts (*i.e.* subtitles, UI texts, etc.)? I can think of the following constraints:

* at least some style effects (*e.g.* bold, italics)
* at least some format string support (*e.g.* `you found %d gold`, `you found {count} gold`)
* be translator-friendly: either easy to grasp, or standard enough that translation companies may already have experience with it

I know about the following but none of them appear to support format strings. Are there any industry standards for that or does every game or engine roll their own format?

* UE4 uses a custom rich text format (example: `Hello <RichText.Emphasis>everyone</>!`)
* Unity uses its own HTML-like format (example: `Hello <b>everyone</b>!`)
* the srt format uses HTML-like syntax, too (example: `Hello <b>everyone</b>!`)
* BBCode is another popular format (example: `Hello [b]everyone[/b]!`)

# Answer
The translation companies I've worked with use CSV or po (gettext) files. However, those formats don't specify how format/replacement strings or text formatting should work.

I've found that labelled replacements like `"you found {count} gold"` work better than numbered placeholders. C# style numbered placeholders resulted in questions from translators about what words replace the `{1}`, etc. That meant I had to compile a legend for each format string before sending out translations.

For text formatting, I'm not sure it matters much so long as you're clear to translators that they shouldn't change that markup or translate anything inside them. We use html-like tags. I think this format will likely be engine-specific because you may inject images into your strings (for button icons) or other game-specific text features.
> 2 votes

# Answer
Use whatever is easiest for you/your team to work with. Personally I always use XML because that means I can parse the tags at the same time as I parse the storage container the strings are in:

```
<Translations Language="en-gb">
    <SomeNPC>
        <!-- An unknown tag <[something] /> is shorthand for <Param Id="[something]" /> -->
        <Greeting>Hello <player />! <weatherReaction /> weather, am I right?</Greeting>
    </SomeNPC>
</Translations>

<!-- Then just use like:
    > i18n.translate("SomeNPC.Greeting", {player: "John", weatherReaction: "Nice"});
    Hello John! Nice weather, am I right?
-->

```

The reason for tags is that it becomes trivially easy to perform "advanced" translations:

```
<CakeCount>
    I have
    <Select>
        <If Var="cakeCount" Equals="0">no</If>
        <If Var="cakeCount" Equals="1">one</If>
        <If Var="cakeCount" GreaterThan="1"><Param Id="cakeCount" /></If>
    </Select>
    <Select>
        <If Var="cakeCount" Equals="1">cake</If>
        <Else>cakes</Else>
    </Select>
</CakeCount>

<!-- Then just use like:
    > i18n.translate("CakeCount", {cakeCount: 6});
    I have 6 cakes
-->

```

As for your question about translation companies, many companies have their own "format" they want the text in (e.g. just a .txt with each translation numbered and on separate lines) so you would follow that. If they don't want "styled" text (with tags etc.) then you just have to work around it or find another company, but most people are aware of what HTML looks like so a simple explanation to not translate the tags should be enough.

If you have in-house translators you just train them in whatever format you decide to use, and XML is easy to understand (translate all text, except stuff between `<` and `>`).
> 1 votes

---
Tags: gui, subtitles
---


title: Proper 2D isometric tile depth sorting?

text:
# Question
Title: Proper 2D isometric tile depth sorting?
I'm using Raylib, and I'm attempting to place tiles on a level, and the algorithm for placing the tiles is working.

The problem is that the player will display ***over*** the walls on the bottom right hand side of the isometric grid.

What am I doing wrong, and does this involve the painter's algorithm?

Here is the code:

#include "raylib.h"
#include <stdint.h>

//Defines
#define COLUMNS 10
#define ROWS 10

//Player
typedef struct Player
{
    int dirX;
    int dirY;
    Texture2D playerTexture;
    Vector2 position;
    struct Player* player;
}Player;

//Change from 2D to Isometric
Vector2 twoDtoIso(Vector2 tilePosition);

void movePlayer(Player* player, int8_t newX, int8_t newY);

int main()
{
    // Initialization
    //-------------------------------------------------------------------------

    const uint8_t TILE_WIDTH    =     32;
    const uint8_t TILE_HEIGHT   =     32;
    const uint8_t PLAYER_OFFSET =     32;
    const float SCREEN_WIDTH    = 640.0f;
    const float SCREEN_HEIGHT   = 352.0f;
    const float SCREEN_CENTER_X = 288.0f;
    const float SCREEN_CENTER_Y =   0.0f;

    InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Isometric Tile placement");

    //These images are loaded from a folder named "images" with
    //isometric cubes that are 64 pixels by 64 pixels
    Texture2D wallTexture   = LoadTexture("images/wallTile.png");
    Texture2D groundTexture = LoadTexture("images/groundTile.png");

    Player player = {0, 0,LoadTexture("images/player.png"),(Vector2){ SCREEN_CENTER_X, PLAYER_OFFSET }};

    uint8_t levelData[COLUMNS][ROWS] =
    {
        {1,1,1,1,1,1,1,1,1,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,2,1}, //<-----The player is designated as 2, ground as 0, and wall tiles as 1
        {1,1,1,1,1,1,1,1,1,1}
    };

    static uint8_t tileType;
    const uint8_t  NUM_COLUMNS = 10;
    const uint8_t  NUM_ROWS    = 10;
    const int8_t   newX        = 32;
    const int8_t   newY        = 16;

    Vector2 coords;
    Vector2 tilePosition;

    SetTargetFPS(30);
    //------------------------End Initialization-------------------------------

    // Main game loop
    while (!WindowShouldClose())
    {
        // Update
        //---------------------------------------------------------------------

        //Player input/movement

        movePlayer(&player, newX, newY);

        //--------------------------End Update---------------------------------

        // Draw
        //---------------------------------------------------------------------
        BeginDrawing();

            ClearBackground(BLACK);

            //place tiles
            for (uint8_t i = 0; i < NUM_ROWS; i++)
            {
                for (uint8_t j = 0; j < NUM_COLUMNS ; j++)
                {
                    tilePosition = (Vector2){(float)j * TILE_WIDTH, (float)i * TILE_HEIGHT};
                    tileType = levelData[i][j];
                    coords = twoDtoIso(tilePosition);

                    if(tileType == 0) //place ground tile
                    {
                         DrawTexture(groundTexture, coords.x + SCREEN_CENTER_X, coords.y + SCREEN_CENTER_Y, WHITE);
                    }
                    else if(tileType == 1) //place wall tile
                    {
                        DrawTexture(wallTexture, coords.x + SCREEN_CENTER_X, coords.y + SCREEN_CENTER_Y, WHITE);
                    }
                    else //otherwise place the player
                    {
                        DrawTexture(player.playerTexture, player.position.x, player.position.y, WHITE);
                    }
                }
            }//end for loop

        EndDrawing();
        //---------------------------------------------------------------------
    }

    // De-Initialization
    //-------------------------------------------------------------------------
    UnloadTexture(groundTexture);
    UnloadTexture(wallTexture);
    UnloadTexture(player.playerTexture);

    CloseWindow();                // Close window and OpenGL context
    //-------------------------------------------------------------------------

    return 0;
}

Vector2 twoDtoIso(Vector2 tilePosition)
{
    Vector2 tempPoint;
    tempPoint.x =  tilePosition.x - tilePosition.y;
    tempPoint.y = (tilePosition.x + tilePosition.y)/ 2;
    return(tempPoint);
}

void movePlayer(Player* player, int8_t newX, int8_t newY)
{
    if (IsKeyPressed(KEY_LEFT))
    {
        player->position = (Vector2){ player->position.x - newX, player->position.y + newY };
    }
    if (IsKeyPressed(KEY_RIGHT))
    {
        player->position = (Vector2){ player->position.x + newX, player->position.y - newY };
    }
    if (IsKeyPressed(KEY_UP))
    {
        player->position = (Vector2){ player->position.x - newX, player->position.y - newY };
    }
    if (IsKeyPressed(KEY_DOWN))
    {
        player->position = (Vector2){ player->position.x + newX, player->position.y + newY };
    }
}

```
</code></pre>

# Answer
> 0 votes
Here's how I got it working. The player tile can be moved with WASD, and some tiles allow the player to move to tiles that are a height of less than 2. The player can collide with tiles that are designated as collision tiles. Make sure you have a folder named "images" with your tiles, where the .c file is located. Using raylib v4.6-dev:

<pre><code>#include <raylib.h>
#include <raymath.h>

#define GRID_WIDTH 8
#define GRID_HEIGHT 8
#define TILE_SIZE 64
#define PLAYER_SPEED 1
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480

// Define tile types (add more as needed)
enum TileType {
    TILE_FLOOR = 0,
    TILE_WALL,
    TILE_TREE,
    TILE_WATER,
    TILE_ELEVATION, // New tile type for elevation
    TILE_GRASS,
};

int playerX = 0;
int playerY = 0;

// 3D array representing the isometric grid with tile types and elevation
int grid[GRID_WIDTH][GRID_HEIGHT][2] = {0}; // Initialize with all floor tiles at elevation 0

// Function to convert grid coordinates to screen coordinates
Vector2 GridToScreen(int x, int y, int elevation) {
    Vector2 screenPos;
    screenPos.x = (x - y) * (TILE_SIZE / 2);
    screenPos.y = (x + y) * (TILE_SIZE / 4) - elevation * (TILE_SIZE / 2);
    return screenPos;
}

// Function to check if the player can move to the specified grid position
bool CanMoveTo(int x, int y) {
    if (x < 0 || x >= GRID_WIDTH || y < 0 || y >= GRID_HEIGHT) {
        // Out of bounds
        return false;
    }

    // Check the tile type and elevation at the specified grid position
    int tileType = grid[x][y][0];
    int elevation = grid[x][y][1];

    // Check if the target tile has an elevation of 1 or is flat ground (elevation 0)
    if (elevation == 1 || elevation == 0) {
        // If the tile is a wall or tree, return false
        if (tileType == TILE_WALL || tileType == TILE_TREE) {
            return false;
        }

        return true; // Otherwise, the player can move to this tile
    }

    // Check if the player is moving from elevation 1 to elevation 2 or vice versa
    int currentElevation = grid[playerX][playerY][1];
    if ((currentElevation == 1 && elevation == 2) || (currentElevation == 2 && elevation == 1)){
        return true;
    }

    return false; // Elevation is 2 or higher, and it's not a valid move from elevation 0
}

int main() {
    InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Isometric Grid with Raylib");
    SetTargetFPS(60);

    // Place wall tiles at specific locations with elevation 1 (you can change these as needed)
    grid[2][5][0] = TILE_WALL;
    grid[3][1][0] = TILE_WALL;
    grid[4][3][0] = TILE_WALL;
    grid[2][4][0] = TILE_WALL;
    grid[3][3][0] = TILE_WALL;

    // Add other tile types (e.g., tree, water, grass) at specific locations and elevations
    grid[1][3][0] = TILE_TREE;
    grid[6][4][0] = TILE_TREE;
    grid[4][1][0] = TILE_WATER;
    grid[0][7][0] = TILE_ELEVATION; // Elevation at (0, 7) represented by the rock tile
    grid[7][0][0] = TILE_GRASS;

    // Set the elevation value for the tile representing the rock elevation
    grid[0][7][1] = 1; // Elevation level of 1 for the rock tile
    grid[1][7][1] = 2; // Elevation level of 1 for the rock tile

    // Load textures
    Texture2D floorTexture     = LoadTexture("images/floorTile.png");
    Texture2D wallTexture      = LoadTexture("images/wallTile.png");
    Texture2D playerTexture    = LoadTexture("images/playerTile.png");
    Texture2D treeTexture      = LoadTexture("images/treeTile.png");
    Texture2D waterTexture     = LoadTexture("images/waterTile.png");
    Texture2D elevationTexture = LoadTexture("images/rockTile.png"); // Texture for elevation (rock tile)
    Texture2D grassTexture     = LoadTexture("images/grassTile.png");

    while (!WindowShouldClose()) {
        // Handle player movement
        if (IsKeyPressed(KEY_W) && CanMoveTo(playerX, playerY - 1)) {
            playerY -= PLAYER_SPEED;
        }
        if (IsKeyPressed(KEY_A) && CanMoveTo(playerX - 1, playerY)) {
            playerX -= PLAYER_SPEED;
        }
        if (IsKeyPressed(KEY_S) && CanMoveTo(playerX, playerY + 1)) {
            playerY += PLAYER_SPEED;
        }
        if (IsKeyPressed(KEY_D) && CanMoveTo(playerX + 1, playerY)) {
            playerX += PLAYER_SPEED;
        }

        // Ensure the player stays within the grid boundaries
        playerX = Clamp(playerX, 0, GRID_WIDTH - 1);
        playerY = Clamp(playerY, 0, GRID_HEIGHT - 1);

        BeginDrawing();
        ClearBackground(BLACK);

        // Render tiles from back to front (lower y-axis first)
        for (int y = 0; y < GRID_HEIGHT; y++) {
            for (int x = 0; x < GRID_WIDTH; x++) {
                Vector2 screenPos = GridToScreen(x, y, grid[x][y][1]); // Use the elevation value

                // Render the tile at grid[x][y] at (screenPos.x, screenPos.y)
                switch (grid[x][y][0]) {
                    case TILE_WALL:
                        DrawTexture(wallTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                        break;
                    case TILE_TREE:
                        DrawTexture(treeTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                        break;
                    case TILE_WATER:
                        DrawTexture(waterTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                        break;
                    case TILE_ELEVATION:
                        DrawTexture(elevationTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                        break;
                    case TILE_GRASS:
                        DrawTexture(grassTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                        break;
                    default:
                        DrawTexture(floorTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                        break;
                }

                // Render the player
                if (x == playerX && y == playerY) {
                    DrawTexture(playerTexture, screenPos.x + SCREEN_WIDTH / 2, screenPos.y, WHITE);
                }
            }
        }

        EndDrawing();
    }

    // Unload textures
    UnloadTexture(floorTexture);
    UnloadTexture(wallTexture);
    UnloadTexture(playerTexture);
    UnloadTexture(treeTexture);
    UnloadTexture(waterTexture);
    UnloadTexture(elevationTexture);
    UnloadTexture(grassTexture);

    CloseWindow();

    return 0;
}
```

# Answer
> 2 votes
You are painting your tiles in the wrong order. Yes, you would use the painters algorithm, which just means, that you draw from back to forward. In your image (I can't really see, where you 0,0 is in the image. 0,0 should be in the top middle of the screen and then like so:

if you "rotate" to change the direction you are viewing you need another draw order. It's normally solved by just inverting a loop from 0-\>n to n-\>0 or something (depends on where you 0,0 is on the image)

---
Tags: 2d, tiles, isometric, c, depth
---


title: OpenTK and GPL license?

text:
# Question
Title: OpenTK and GPL license?
I want to open source my project and use a GPL license with OpenTK.

Can a GPL license be used with OpenTK?

# Answer
OpenTK is MIT licensed and includes additional 3rd party code from ILM (Industrial Light & Magic - Lucasfilm).

If it were my project, I would do a deep dive into the ILM code and make certain that you have full authorization to use it. https://github.com/opentk/opentk/blob/master/THIRD\_PARTIES.md

Generally speaking, a GPL Licensed Project can include MIT Licensed (ie, Public Domain) code.

> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software

Combining Public Domain code (~80% of "OSI Approved Open Source" software) with GPL style Free-Software licensed code is fine, because you can do whatever you like with items in the public domain.

Good luck with your project!
> 0 votes

---
Tags: licensing, opentk
---


# Question
Title: How to copy the Renderer Present screen result into a surface or texture?
Is it possible to copy into a `SDL_Surface` what is displayed in the screen from a `SDL_RendererPresent`?

using `SDL_GetWindowSurface` just return a black surface not the rendered scene as it is not accessing directly the video ram.

using `SDL_GetRendererTarget` if it is the "default" (the screen) is just a `NULL` value.

is there any function to copy the `SDL_RendererPresent` result into a `SDL_Surface` or even a `SDL_Texture`?

# Answer
It is possible using `SDL_RenderReadPixels`, e.g.:

```

// SDL_Renderer* renderer
SDL_Window* window = SDL_RenderGetWindow(renderer);
SDL_Surface* screen_surf = SDL_GetWindowSurface(window);
if (SDL_RenderReadPixels(renderer, nullptr, 0, screen_surf->pixels, screen_surf->pitch) != 0)
        {
            // error use SDL_GetError()
        }

// at this point in screen_surf there is the rendered content from the screen.

```
> 0 votes

---
Tags: sdl2
---


# Question
Title: "End of line expected" error preventing me from opening game
I wanted to open my game to check that everything is working properly, but whenever I try to open the project, it redirects me to the script instead. This is the message below:

> I'm sorry, but errors were detected in your script. Please correct the errors listed below, and try again.
>
> ```
> File "game/script.rpy", line 388: end of line expected.
>    jump skip:
>             ^
> Ren'Py Version: Ren'Py 7.4.11.2266
> Sat Jun  4 21:37:05 2022
>
> ```

(For reference, I'm trying to skip some dialogue that's only available once you're on the normal ending. I've attached a picture to help)

I tried indenting it with one-two lines, putting all the dialogue after the indention line and putting the label skip: on a different indention line, but none of it has worked.

How do I fix this?

# Answer
This error:

> ```
> File "game/script.rpy", line 388: end of line expected.
>    jump skip:
>             ^
> Ren'Py Version: Ren'Py 7.4.11.2266
> Sat Jun  4 21:37:05 2022
>
> ```

This is telling me that the line 388 of the file "game/script.rpy" looks like this:

```
   jump skip:

```

*Said line 388 is not included in the attached image, which goes from line 395 to 436.*

The cause of the error is that you should not put a `:` on a `jump`. The `:` is for code blocks, but `jump` isn't one.

The reiterate the error message: the parser was expecting that the line ended, but instead of that, it found a `:`.
> 2 votes

---
Tags: python, renpy
---


title: Determine which direction to rotate

text:
# Question
Title: Determine which direction to rotate
Not sure if this belongs here or on the Math Exchange site; it's probably a simple math concept that I'm missing.

I have a 2D sprite with a rotation (let's call it ***A***), and I want to slowly rotate it until it's at a new rotation (***B***). Depending on where ***A*** is, I'll rotate right or left, which ever gets me to ***B*** faster. ***A*** is constantly changing as it rotates towards ***B***, and ***B*** is also able to change.

I'm currently taking the difference of ***B*** \- ***A***, and rotating left (CCW) if it's positive, and rotating right (CW) if it's negative. This almost works, but breaks when the target crosses the boundary at *0*/ and changes signs.

In the first image, you'll see how my current logic works as expected:

***B*** \- ***A*** ≈ 5.76 - 5.23 = 0.53 = turn CCW.

But, if ***B*** continues to rotate left, it will rotate past  and result in the sprite turning CW, which is slower than turning CCW:

***B*** \- ***A*** ≈ 0.17 - 5.50 = -5.33 = turn CW.

Any ideas would be appreciated, thanks!

NOTES:

* I'm using Bevy + Rust, but this seems like a generalized math question so not sure if that's important
* I've tried this with angles ranging from \[-π, π\] (instead of \[0, 2π\]), but it has the same issue when the angle crosses the boundary between π and -π.

# Answer
The maximum amount you should ever rotate is half a turn, since if you're rotating more than that, it would have been faster to go the other way. You should check your final result to see if it its magnitude is greater than Pi. If it is, your "shortest path" is greater than half a rotation, indicating that you have a modulo issue and need to add 2\*Pi to B.

In your example, a result of -5.33 is almost one full turn, which obviously isn't the fastest way to reach a heading. Since 5.33 is greater than pi, add 2\*Pi to the result, yielding a value of 0.95, which is the correct minimum distance to turn counterclockwise.
> 0 votes

# Answer
Finding the minimum rotation from an orientation ***A*** to a target orientation ***B*** is equivalent to finding the *signed angle* between ***A*** and ***B***, then applying the rotation.

This excellent answer on Stack Overflow addresses this very problem by providing a working formula in modular arithmetic.

When working with angles, we call a signed angle a number where:

* Its value is the smallest of the two angles formed by a source vector with direction ***A*** and a target vector with direction ***B***. Its absolute value is always 0-180.
* Its sign is the rotation direction (CCW if positive, CW if negative) to accomplish the smallest rotation possible.

By combining the above and the modulo operator, such a function returns a value between -180 and 179. A simple Python implementation would look like this:

```
def signed_angle(source_angle, target_angle):
    a = target_angle - source_angle
    a = (a + 180) % 360 - 180
    return a

```

Sample execution of the above:

```
>>> signed_angle(0,90)
90
>>> signed_angle(72,254)
-178
>>> signed_angle(135,-217)
82

```

Additional math considerations are included in the linked answer by its original author. Also, this answer assumed angles were expressed in degrees, but converting it to work with radians is trivial.
> 0 votes

---
Tags: mathematics
---


# Question
Title: Can 'hotseat multiplayer' refer only to turn-based games?
According to Wikipedia, "hotseat" is a multiplayer mode of only turn-based games. But can one use "hotseat" to describe a one-screen real-time multiplayer game?

E.g., a game session can occur on one screen and players share a keyboard. Like in classic beat-em-ups and fightings. Is this 'hotseat'? Or just 'same-device multiplayer'?

# Answer
It can only be used to describe games in which only one player is playing at a time.
The players take turns to play on the same device, so it is not really possible to apply this on real-time games.

The term 'hotseat' is a metaphor in which the seat is too hot for the player to sit for too much time, forcing him to leave the seat to avoid pain.

Although the meaning is completely different, the metaphor is similar to the hot potato one.
> 2 votes

---
Tags: multiplayer, terminology
---


# Question
Title: Animations don't transition when prefab instantiated by code
I am working on a script that responds to the player pressing a button by instantiating a prefab into the scene.

The problem is the animation is not working on the spawned prefab. The conditions of the Animator are being met and switching to them but it's stuck in the first animation it starts in (In this case, the walking animation), but when I drag the prefab out by hand, the animation plays just fine when the conditions are met.

What is up with my Unity code that is causing the instantiated prefab to not work while the prefab itself works fine when dragged in?

Code for the AI

```
{

    public NavMeshAgent NAV;

    private Animator Anim;

    public float BlockTimer = 3f;
    public float AttackRadius = 5f;
    public float AllyAttackTime = 2f;
    public float Speed = 5f;
    public float Health = 10f;
    public float AllySpotRange = 10f;

    bool EnemyAttackPointCheck, EnemySightCheck;
    bool HasAttacked = false;
    bool HasBlocked = false;

    string[] AllyNumbers;

    public Transform EnemyObj;
    public Transform AllyEndPoint;

    public LayerMask EnemyFaction;
    public LayerMask Player;

    private void Awake()
    {
        NAV = GetComponent<NavMeshAgent>();
        Anim = GetComponent<Animator>();
    }

    private void Update()
    {
        EnemySightCheck = Physics.CheckSphere(transform.position, AllySpotRange, EnemyFaction);
        EnemyAttackPointCheck = Physics.CheckSphere(transform.position, AttackRadius, EnemyFaction);

        if (!EnemyAttackPointCheck && !EnemySightCheck)
        {
            AllyMove();
            Anim.SetTrigger("IsWalking");
        }

        if (!EnemyAttackPointCheck && EnemySightCheck)
        {
            AllySpotted();
            Anim.SetTrigger("IsMarching");
        }

        if (EnemyAttackPointCheck && EnemySightCheck)
        {
            AllyAttack();
            Anim.SetTrigger("IsAttacking");
        }
    }
    void AllyMove()
    {
        Anim.SetBool("IsWalking", true);
        Anim.SetBool("IsMarching", false);
        Anim.SetBool("IsAttacking", false);
        Anim.SetBool("IsBlocking", false);

        NAV.SetDestination(AllyEndPoint.position);
    }

    void AllySpotted()
    {
        Anim.SetBool("IsWalking", false);
        Anim.SetBool("IsMarching", true);
        Anim.SetBool("IsAttacking", false);
        Anim.SetBool("IsBlocking", false);

        NAV.SetDestination(EnemyObj.position);

        Speed = 3f;
    }

    void AllyAttack()
    {
        NAV.SetDestination(transform.position);

        transform.LookAt(EnemyObj);

        if (!HasAttacked)
        {
            Anim.SetBool("IsWalking", false);
            Anim.SetBool("IsMarching", false);
            Anim.SetBool("IsAttacking", true);
            Anim.SetBool("IsBlocking", false);

            HasAttacked = true;

            Invoke(nameof(ResetAttackTimer), AllyAttackTime);
        }

        if (HasAttacked && !HasBlocked)
        {
            HasBlocked = true;

            Anim.SetBool("IsWalking", false);
            Anim.SetBool("IsMarching", false);
            Anim.SetBool("IsAttacking", false);
            Anim.SetBool("IsBlocking", true);

            Invoke(nameof(ResetBlockTimer), BlockTimer);
        }
    }

    void ResetAttackTimer()
    {
        Anim.SetBool("IsAttacking", false);

        HasAttacked = false;
    }

    void ResetBlockTimer()
    {
        Anim.SetBool("IsBlocking", false);

        HasBlocked = false;
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, AttackRadius);

        Gizmos.color = Color.green;
        Gizmos.DrawWireSphere(transform.position, AllySpotRange);
    }
}

```

Then the code to instantiate the AI when a button is pressed:

```
{

    private Animator Anim;

    public int PlayerGold = 25;
    public int PlayerMaxTroops = 15;

    private int TroopCounter;

    private float GoldCountDownTimer = 10;
    private float ResetTimer = 10;

    public Transform AllyEndPoint;
    public Transform BaseSpawnPoint;
    public Transform FootmanObj;

    public Text CounterTroop;
    public Text CounterGold;

    private void Awake()
    {
       Animator Anim = GetComponent<Animator>();
    }

    public void BottunPressed()
    {
        UnitSpawner();
    }

    private void Update()
    {
        GoldCountDownTimer -= Time.deltaTime;

        if (GoldCountDownTimer < 0 || GoldCountDownTimer == 0)
        {
            GoldCountDownTimer = ResetTimer;
            PlayerGold += 4;
        }

        CounterTroop.text = TroopCounter.ToString() + "/" + PlayerMaxTroops;
        CounterGold.text = PlayerGold.ToString();
    }

     void UnitSpawner()
    {
        if (PlayerGold == 5 || PlayerGold > 5 && TroopCounter < PlayerMaxTroops)
        {
            Instantiate(FootmanObj, BaseSpawnPoint.position, BaseSpawnPoint.rotation);
            PlayerGold -= 5;
            TroopCounter++;
            Debug.Log("Ally spawned " + TroopCounter);
        }
        else
            return;
    }
}

```

# Answer
> 0 votes
I've just fixed this issue in my own game. My issue was I had two animator controllers, one on my character model and one on my empty gameobject I used for my collider. Removing one of the animator controllers seemed to fix my issue. I think having the 2 animator controllers was confusing things, so it was able to recognise that it should be playing the first animation repeatedly but when it came to changing animation (for example doing Anim.SetBool) it didn't know which animator to change the bool for.

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


# Question
Title: Navmesh awkward path generation with string pulling due to "inner" vertices
I've identified a problem and a possible solution related to navmesh-based pathfinding. Before diving in, I'll preface my post with some questions to keep in mind as you read:

* Is this a known problem that people have solved before?
* Is there a term for the problem that could help me search for information related to it?
* Is the solution I came up with an existing idea? If so is there a name for the algorithm or some other search term I could use to find more information?
* Is there a better solution? If so, please point me to it.

For reference, I'm using images from http://jceipek.com/Olin-Coding-Tutorials/pathing.html#navigation-meshes and generally following the advice laid out there.

tl;dr of that blog post is

> Decompose your walkable area into a navmesh, treating convex polygons as nodes and their borders as edges so that you can perform an A\* search to get from point A to point B. To translate from "node ids" back to real points, use string-pulling.

Here's a copy of the example space:

And an example generated path after performing string pulling:

So far so good.

But I realized this approach generates an awkward path in a situation like this:

In this situation, a trio of nodes are all adjacent to each other, and so the A\* will generally choose a path directly from the starting node to the ending node, despite an intuitive understanding that the agent can move in a straight line from A to B which travels through a different polygon.

I've been working on a solution to this problem and so far my best idea is to apply a transformation to the nav mesh. My description of this will be a little hazy as I'm making up terminology to describe the approach...

* Define a *shared edge* as a line segment that is shared by two convex polygons in the navmesh. Maybe a.k.a. a "portal" for string-pulling purposes.
* Define an *inner vertex* as a vertex in the navmesh for which all attached line segments are "shared edges". The vertex in the center of the three polygons in the image above is an *inner vertex*.
* Identify an *inner vertex*. Follow its attached *shared edges* to what I'll call *neighbor vertex*. (possible improvement; If the *neighbor vertex* is also an *inner vertex*, recurse to its neighbors until all of the neighbors are non-*inner*.)
* Remove all *shared edges* from the navmesh that were traversed in the previous step, forming a new polygon whose border is defined by the *neighbor vertices* in the previous step. Redefine the edges accordingly (I'll hand-wave that)
* Repeat until no *inner vertices* remain.

The result of this on the example above should result in this:

And with the same A-B path from before, the string-pulling should now result in a straight line:

I believe that as long as the navmesh has no *inner vertices*, all paths generated with the approach described in the linked blog post should seem "natural" and not have any surprise corners in what seems like open space.

Per my questions at the beginning of this post, I'm looking for more information, e.g. has anybody else solved this problem before, is there a better way to do it, and is there even a name/term for this problem?

# Answer
The string pulling algorithm should use the walls as the borders, not the corners of Nav-Mesh intersections.

It's still possible to get a non-optimal path when eg. the pathfinder goes around an obstacle in a non-optimal way. This non-optimal nature of string-pulling is just something game developers need to live with. There are optimal algorithms, but they tend to be much slower.

Of note, there are also other fast approximation algorithms that don't rely on string-pulling.
> 1 votes

# Answer
This is not a problem with string pulling algorithm, but with A\* algorithm.

For this non-grid graph, using midpoints of edges to calculate the distance(cost) is better than using midpoints of polygons.
> 0 votes

---
Tags: path-finding, terminology, navmesh
---


# Question
Title: When switching between two scenes: MissingReferenceException: The object of type '...' has been destroyed but you are still trying to access it
I recreated the problem in a new project to check and test the problem, but I don't understand it.

Two scenes:

## First scene

A GameObject with this script that simply jumps to the second scene.

*script1\_S1.cs*

```
void Update() {
    if (Input.GetKeyDown(KeyCode.A)) SceneManager.LoadScene("Scene2", LoadSceneMode.Single);
}

```

## Second scene

Two GameObjects with two different scripts.

The first script can go back to scene1 or invoke an event.

*script1\_S2.cs*

```
public delegate void OnMyEvent ();
public static event OnMyEvent onMyEvent;

void Update() {
    if (Input.GetKeyDown(KeyCode.A)) SceneManager.LoadScene("Scene1", LoadSceneMode.Single);
    if (Input.GetKeyDown(KeyCode.S)) onMyEvent?.Invoke();
}

```

The second script registers the event and loads the `rootVisualElement` of the `UIDocument` included as a component in the same `GameObject` of this script.

*script2\_S2.cs*

```
private void Awake() {
    ScriptCube1.onMyEvent += () => { Log(); };
}

public void Log() {
    gameObject.GetComponent<UIDocument>().rootVisualElement.style.display = DisplayStyle.Flex;
    Debug.Log("Cliccked");
}

```

### Steps to reproduce the error

If from the first scene I press `A` I go to the second. In the second one I press `S` and the console prints `Clickcked`, and everything works fine. But if I go back to scene 1, and again to scene 2, if I hit `S`, I get this error: `MissingReferenceException: The object of type '...' has been destroyed but you are still trying to access it.`.

`SceneManager.LoadScene` Shouldn't it load the scene as if it were the first time? What am I missing?

Thank you.

---

*After writing all the question I have a doubt. But maybe the problem is that the event has not been deregistered? the error is on the `gameObject` as if it didn't exist anymore. With `SceneManager.LoadScene("Scene1", LoadSceneMode.Single);` shouldn't it unregister all events in `Scene2`? Should I unregister all events? or do I have to use `SceneManager.UnloadScene` explicitly?*

# Answer
It all comes down to the static. It makes the life both easier and harder. Since onMyEvent is static, there is only one of it. That means, even if you destroy the scene and reload it, you get the same onMyEvent with all the values assigned from the last scene back.

Since you are assigning a function to it on Awake, you point now twice to the Log function. This can cause errors since to what we originally pointed might got already destroyed.

The clean way would be to remove the listener/ subscription in the OnDestroy of the scene or set the event null if you are sure there are no side effects (since there can always be the option that other scripts are as well adding their listeners to it). Another option is to remove the static modifier, a new scene would create a new, empty version of the event.
> 1 votes

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