title: Visual shader dropdown missing

text:
# Question
Title: Visual shader dropdown missing
I can't seem to create a visual shader in godot 4, in order to use the visual shader editor.

what am I missing?

# Answer
> 1 votes
Nothing. After you choose to make a New Shader (the option you see), Godot will ask the type in the Create Shader window:

---
Tags: shaders, godot-4
---


# Question
Title: KinematicBody2D stutters/moves back and forth
I'm working in Godot 3.5, and trying to set up a navigation polygon for my kinematic body to mode around inside, but when I try to send it to some point, the body 'stutters'/moves back and forth in the same place.

This my code:

```
extends KinematicBody2D

onready var nav_agent := $NavigationAgent2D
onready var path := $Path

var path_q : Array = []

var direction
var velocity
func _ready():
    nav_agent.set_target_location(position)
    path.set_as_toplevel(true)

func _physics_process(delta):

    if not _arrived_to_location():
        direction =  position.direction_to(nav_agent.get_next_location())
        velocity = direction * 250
        move_and_slide(velocity)
    elif nav_agent.is_target_reached() and not path_q.empty():
        nav_agent.set_target_location(path_q[0])
        path_q.remove(0)
    else:
        path.clear_points()

func move_to(coord:Vector2):
    if path_q.empty():
        path.points = [position]

    path.add_point(coord)
    path_q.append(coord)

func _arrived_to_location():
    return nav_agent.is_target_reached() and path_q.empty()

```

`path` is just to visualize where the body is supposed to go. `path_q` is a queue of points where the body has to go in that order.

Since this is just an image, you can't see some stuff. `UnitToken.position` and `UnitToken.direction` values go crazy, they always are changing but not enough to make `UnitToken` move beyond that point, so that's where the stutter comes from, but `nav_agent.get_next_location()` is always the same point.

Any ideas what I'm doing wrong?

# Answer
> 2 votes
Are you not overshooting your target?

You have this code:

```
direction =  position.direction_to(nav_agent.get_next_location())
velocity = direction * 250
move_and_slide(velocity)

```

Here (assuming no obstacles) the body would move `velocity * delta`, which might or might not be more than the distance to the target.

This is the distance to the target:

```
var distance := position.distance_to(nav_agent.get_next_location())

```

And thus, the maximum speed would be (remember that speed is distance over time):

```
var max_speed := distance / delta

```

Then you can limit the length of `velocity` to that:

```
direction =  position.direction_to(nav_agent.get_next_location())
var distance := position.distance_to(nav_agent.get_next_location())
var max_speed := distance / delta
velocity = direction * min(250, max_speed)
move_and_slide(velocity)

```

Which, by the way, is the same as this:

```
var displacement := nav_agent.get_next_location() - position
var distance := displacement.length()
var max_speed := distance / delta

direction =  displacement.normalized()
velocity = direction * min(250, max_speed)
move_and_slide(velocity)

```

---
Tags: 2d, physics, movement, godot-3, kinematic
---


title: Instantiate prefab behind moving player

text:
# Question
Title: Instantiate prefab behind moving player
I'm trying to instantiate a bomb prefab behind the player.

The script below works fine when the y rotation is 0,90,180,360. The bomb is instantiated behind the player.

But for other angles, the bomb is not instantiated directly behind the player. Is there any way to use maybe sin/cos functions (depending on the y rotation) to get the bomb to instantiate directly behind the player?

I'm using a cube as the player and sphere as bomb. The sphere is scaled to 0.3.

```
private float yRotation;

void FixedUpdate()
{
   transform.position += transform.forward * speed;
   float rotation = Input.GetAxis("Horizontal");
   transform.Rotate(Vector3.up * rotation * 180.0f * Time.deltaTime);//Keyboard movement

   yRotation = transform.localEulerAngles.y;

    if (Input.GetKey(KeyCode.B))
    {
       PlaceBomb();
    }
 }

   void PlaceBomb(){

       if (yRotation >= 0 && yRotation < 90)
        {
            Instantiate(bombPrefab, new Vector3(transform.position.x, 0, transform.position.z - 1f), Quaternion.identity);
        }
        if (yRotation >= 90 && yRotation < 180)
        {
           Instantiate(bombPrefab, new Vector3(transform.position.x - 1, 0, transform.position.z), Quaternion.identity);
        }
        if (yRotation >= 180 && yRotation < 270)
        {
             Instantiate(bombPrefab, new Vector3(transform.position.x, 0, transform.position.z + 1), Quaternion.identity);
        }
        if (yRotation >= 270 && yRotation <= 360)
        {
           Instantiate(bombPrefab, new Vector3(transform.position.x, 0, transform.position.z - 1), Quaternion.identity);
        }

   }

```

# Answer
> 1 votes
We can use the `transform.forward` property, and reverse it to put the object behind the player.

```
void PlaceBomb(){
    float distance = 1;
    var position = transform.position - (transform.forward * distance);
    Instantiate(bombPrefab, position, Quaternion.identity);
}

```

Or we can use `transform.TransformPoint()` to convert a point that is directly behind us in local space into the equivalent point in world space:

```
void PlaceBomb(){
    float distance = 1;
    var position = transform.TransformPoint(new Vector3(0, 0, -distance));
    Instantiate(bombPrefab, position, Quaternion.identity);
}

```

---
Tags: unity, c#, angles, prefabs
---


title: Limit FPS in Scene view Unity

text:
# Question
Title: Limit FPS in Scene view Unity
Is there a way to limit the FPS in the **Scene view** of Unity?

I tried `Application.targetFrameRate` but this only works in the game view.

# Answer
> 2 votes
You can create an FPS limiting script and add \[ExecuteInEditMode\] to it.

Additionally, you can do it in the Nvidia control panel.

1. Manage 3d settings.
2. Select Unity in the app list.
3. Set the settings: max frame rate = 30/60.

# Answer
> 0 votes
All in all there are only two solutions to limit FPS for scene view:

1. Re-check vsync in game view every time unity starts || exit game mode (unity bug). By some reason it affects scene view as well
2. Edit -\> Preferences -\> General -\> Ineraction Mode: Monitor Refresh Rate

---
Tags: unity
---


# Question
Title: How to set world rotation directly in Stride?
I just started looking into Stride as a replacement for Unity, and I'm trying to rewrite some scripts.

My question is: How do you set the world rotation of a transform component?

In other words, what would be Stride's equivalent of using `transform.rotation = someQuaternion;` in Unity?

I found some helpful info here, but it doesn't seem to mention how to set the world rotation directly. Just local rotation.

# Answer
> 2 votes
In Unity, the `.rotation` property works something like this...

```
public Quaternion rotation {
   get {
       return parent.rotation * localRotation;
   }

   set {
       localRotation = Quaternion.Inverse(parent.rotation) * value;
   }
}

```

(eliding some complexity around "what if the object doesn't have a parent?" and options to cache data / use dirty flags to avoid redundant computation)

So to implement something similar in Stride, you can take the parent's world matrix and extract the \[best-fitting\] rotation as a quaternion. Invert that, then multiply by the net rotation you want to set. This will give you a quaternion representing the *difference* between the rotation you want and the parent's rotation. Multiply it on the correct side to ensure it's expressed relative to the parent coordinate space, not relative to the world. Then that quaternion product will be directly usable as a local rotation for your child object.

I note "best-fitting" because it's possible for a matrix to not be a simple combination of translation, rotation, and axis-aligned scale. Even if each individual object in a transform hierarchy is transformed in only these ways, the net result can be a shear, making the "correct" rotation component ambiguous — more than one rotation can give the same output, by changing the shear component to compensate. If you stick to uniform scales at non-leaf nodes though, you will not have problems with this.

---
Tags: rotation, transformation, stride
---


# Question
Title: How do I configure Godot 4.1.1 to use Rider as the IDE for C#?
I can't find out how to do this. I've installed the godot plugin into Rider.

I found two tutorials, one says to open Godot, and go into Project Settings and find Mono and change some settings. However for me, the Mono option does not exist and I can't see any other options that would work.

The second tutorial I found said to point Rider at the Godot folder, and it would detect that it was a Godot project. I did this and it didn't detect that it was a Godot project and I don't have any intellisense.

I am using the Mono version of Godot.

Can someone advise how to get Rider to work? For unity, I simply pointed it in the settings to Rider and it worked perfectly without any faff, but Godot is proving difficult.

I don't have enough rep to create a Rider tag.

# Answer
Took me a while to get this working.

Ensure you're using Mono godot.

Go to Project \> Tools \> C# \> Create C# Solution

Then open the solution within Rider, and ensure you have the Godot plugin installed.

It should automatically load the Godot interface, but if it doesn't (which it didn't for me) you can right click the `.sln` file within Rider and open it (even if the project is already open). It should then detect it and work.
> 4 votes

---
Tags: c#, godot
---


title: 2D Batching and correct draw order

text:
# Question
Title: 2D Batching and correct draw order
I'm encountering a design challenge while developing my 2D C++ OpenGL engine. I'm using a batching technique for rendering my drawable objects, and I want to ensure they are drawn in the same order that I call the 'draw' function. For example

```
Renderer::draw(m_player);
Renderer::draw(m_playerHealthBox):
Renderer::draw(m_enemy);
Renderer::draw(m_enemyHealthBox);

```

I aim to have the enemy health box appear in front, with the player being positioned furthest in the background.

The issue is that I can't easily sort my objects within the Renderer because I'm using different vertex structures for sprites, rectangles, texts, and circles. Consequently, when I flush my objects, the last flushed object type (e.g., rectangles) always ends up on top. I'm struggling to find a way to achieve the correct drawing order while still utilizing batching, without resorting to a single vertex vector and a monolithic shader to handle all cases, which doesn't seem like a great idea to do.

I've also attempted to use depth testing and the z-buffer (firstly changing my vertex positions to Vector3f type), but it doesn't seem to work as expected. I tried manually setting the z-values for each object, such as assigning 'z = 1' for sprite1, 'z = 2' for sprite2, and 'z = 3' for rectangle1 etc, but the correct order is still not reflected on the screen (even when experimenting with different depth testing functions). Do you have any suggestions or tips to address this issue? Many thanks.

My simplified setup:

struct Vertex
{
    Vector4f color = { 1.0f, 1.0f, 1.0f, 1.0f };
    Vector2f position;
    Vector2f textureCoords;

    float textureIndex;
};

struct LineVertex
{
    Vector4f color = { 1.0f, 1.0f, 1.0f, 1.0f };
    Vector2f position;
};

class Renderer
{
public:
    void draw(Ref<Sprite> sprite)
    {
        for (int i = 0; i < 4; i++)
            sprites.vertices[sprites.verticesCount + i] = sprite.getVertices()[i];

        sprites.verticesCount += 4;
    }

    void draw(Vector2f start, Vector2f end, Color color)
    {
        lines.vertices[lines.verticesCount + 0] = { start, color };
        lines.vertices[lines.verticesCount + 1] = { end, color };
        lines.verticesCount += 2;
    }

    void start()
    {
        sprites.verticesCount = 0;
        lines.verticesCount = 0;
    }

    void flush()
    {
        flushLines();
        flushSprites();
    }

private:
    void flushLines()
    {
        //bind line shader, vertexArray, set vertexArray data etc. one draw call
    }

    void flushSprites();
    {
        //bind line shader, vertexArray, set vertexArray data etc. one draw call
    }

    struct Lines
    {
        Ref<Shader> shader;
        Ref<VertexArray> vertexArray;
        Ref<VertexBuffer> vertexBuffer;
        std::array<LineVertex, MAX_LINES_VERTICES> vertices;

        uint32 verticesCount = 0u;
    } lines;

    struct Sprites
    {
        Ref<Shader> shader;
        Ref<VertexArray> vertexArray;
        Ref<VertexBuffer> vertexBuffer;
        std::array<Vertex, MAX_SPRITES_VERTICES> vertices;
        std::array<Ref<Texture>, MAX_TEXTURE_SLOTS> textures;

        uint32 verticesCount = 0u;
        uint32 texturesCount = 0u;
    } sprites;
}

```

# Answer
Disable depth testing for the health boxes. No matter when they are drawn they are always on top.
> 0 votes

---
Tags: opengl, c++, spritebatch, draw-order, batching
---


# Question
Title: How to delete a face of a Primitive Cube
This code uses a Raycast to get the vertices, triangles, etc. of a Primitive Cube, them using RaycastHit.triangleIndex, I can get the triangle that the Raycast hitted, but there is a easy way to get the another triangle? So that I can delete the whole face that the Raycast hitted?

I tryied modifying **x** in \[hit.triangleIndex * 3 + **x**\] to another values, but all the combinations that I tried deleted triangles from another faces.

```
if (Input.GetMouseButtonUp(0))
{
        RaycastHit hit;

        var camera = Camera.main;

        if (!Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), out hit))
        {
            return;
        }

        var meshCollider = hit.collider as MeshCollider;

        if (meshCollider == null || meshCollider.sharedMesh == null)
            return;

        var mesh = meshCollider.sharedMesh;
        var vertices = mesh.vertices;
        var triangles = mesh.triangles;
        Transform objectPosition = hit.transform;

        var p0 = vertices[triangles[hit.triangleIndex * 3 + 0]];
        var p1 = vertices[triangles[hit.triangleIndex * 3 + 1]];
        var p2 = vertices[triangles[hit.triangleIndex * 3 + 2]];

        GameObject newCube = new GameObject();
        newCube.transform.position = objectPosition;

        newCube.AddComponent<MeshFilter>();
        newCube.AddComponent<MeshRenderer>();

        newCube.GetComponent<MeshRenderer>().material = defaultMaterial;

        Mesh mesh = new Mesh()

        for (int i = 0; i < triangles.Count; i+=3)
        {
            bool trianglePoint1 = (triangles[i + 0] == p0);
            bool trianglePoint2 = (triangles[i + 1] == p1);
            bool trianglePoint3 = (triangles[i + 2] == p2);

            if (trianglePoint1 && trianglePoint2 && trianglePoint3)
            {
                triangles.RemoveRange(i, 3);
            }
        }
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        newCube.GetComponent<MeshFilter>().mesh = mesh;
}

```

# Answer
> 1 votes
I found a link that helped me to solve this using normals. To solve this, first you calculate the normals of each point of the triangle that the Raycast hitted:

```
var normalHittedTriangle0 = normals[triangles[hit.triangleIndex * 3 + 0]];
var normalHittedTriangle1 = normals[triangles[hit.triangleIndex * 3 + 1]];
var normalHittedTriangle2 = normals[triangles[hit.triangleIndex * 3 + 2]];

```

And them the normal of the face of the cube:

```
var hittedTriangleNormal = ((normalHittedTriangle0 + normalHittedTriangle1 + normalHittedTriangle2) / 3);

```

And them you loop through all the triangles in the Cube. Get the normal of each point of the triangle, get the normal of the whole triangle and check if it match with the normal of the triangle that the Raycast hitted, if it matched add it to a list.

```
List<int> trianglesToRemove = new List<int>();

for (int i = 0; i < triangles.Length; i += 3)
{
        var p0 = vertices[triangles[i + 0]];
        var p1 = vertices[triangles[i + 1]];
        var p2 = vertices[triangles[i + 2]];

        p0 = normals[triangles[i + 0]];
        p1 = normals[triangles[i + 1]];
        p2 = normals[triangles[i + 2]];

        if (((p0 + p1 + p2) / 3) == hittedTriangleNormal)
        {
                trianglesToRemove.Add(triangles[i + 0]);
                trianglesToRemove.Add(triangles[i + 1]);
                trianglesToRemove.Add(triangles[i + 2]);
        }
}

```

Loop through the triangles of the Cube by a step of 3 (Because triangles are grouped by 3), find the 2 triangles that match with the list and then if it matched, remove it from the triangles of the Cube.

```
for (int i = 0; i < triangles.Length; i+=3)
{
        bool v1 = (triangles[i + 0] == trianglesToRemove[0]);
        bool v2 = (triangles[i + 1] == trianglesToRemove[1]);
        bool v3 = (triangles[i + 2] == trianglesToRemove[2]);

        if ((v1 && v2 && v3))
        {
                triangles.RemoveRange(i, trianglesToRemove.Count);
        }
}

```

All the code:

```
if (Input.GetMouseButtonUp(0))
{
        RaycastHit hit;

        var camera = Camera.main;

        if (!Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), out hit))
        {
           return;
        }

        var meshCollider = hit.collider as MeshCollider;

        if (meshCollider == null || meshCollider.sharedMesh == null)
           return;

        var mesh = meshCollider.sharedMesh;
        var triangles = mesh.triangles;
        var normals = mesh.normals;
        Transform objectPosition = hit.transform;

        var normalHittedTriangle0 = normals[triangles[hit.triangleIndex * 3 + 0]];
        var normalHittedTriangle1 = normals[triangles[hit.triangleIndex * 3 + 1]];
        var normalHittedTriangle2 = normals[triangles[hit.triangleIndex * 3 + 2]];

        var hittedTriangleNormal = ((normalHittedTriangle0 + normalHittedTriangle1 + normalHittedTriangle2) / 3);

        List<int> trianglesToRemove = new List<int>();

        for (int i = 0; i < triangles.Length; i += 3)
        {
            var p0 = vertices[triangles[i + 0]];
            var p1 = vertices[triangles[i + 1]];
            var p2 = vertices[triangles[i + 2]];

            p0 = normals[triangles[i + 0]];
            p1 = normals[triangles[i + 1]];
            p2 = normals[triangles[i + 2]];

            if (((p0 + p1 + p2) / 3) == hittedTriangleNormal)
            {
                trianglesToRemove.Add(triangles[i + 0]);
                trianglesToRemove.Add(triangles[i + 1]);
                trianglesToRemove.Add(triangles[i + 2]);
            }
        }

        GameObject newCube = new GameObject();
        newCube.transform.position = objectPosition;

        newCube.AddComponent<MeshFilter>();
        newCube.AddComponent<MeshRenderer>();

        for (int i = 0; i < triangles.Length; i+=3)
        {
            bool v1 = (triangles[i + 0] == trianglesToRemove[0]);
            bool v2 = (triangles[i + 1] == trianglesToRemove[1]);
            bool v3 = (triangles[i + 2] == trianglesToRemove[2]);

            if ((v1 && v2 && v3))
            {
                triangles.RemoveRange(i, trianglesToRemove.Count);
            }
        }

        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        newCube.GetComponent<MeshFilter>().mesh = mesh;
}

```

---
Tags: unity
---


# Question
Title: How do I instantiate a scene and change properties on it in C#?
Using Godot 4, following a tutorial but the tutorial is in GDScript. It is hard to find one for C# so I am trying to convert it as I go.

I made a scene called Coin and I have a scene called Main which is my main scene.

I want to instantiate a coin onto my scene.

Here's the GDScript:

```
var c = coin_scene.instantiate()
add_child(c)
c.someprop = somevalue

```

This is my C# code:

```
[Export] public PackedScene CoinScene; // In my Main scene, I drag the coin.tscn onto it

// Ready method:
var coin = CoinScene.Instantiate();
AddChild(coin); // This adds the coin to my scene but at 0,0 ie default.
coin.someprop = x // Error since `coin` is not an instance of `coin.cs`

```

The `coin.cs` file is a script attached to my coin scene. However I can't find a way to access it.

I have seen some people say you can just cast it, but it just becomes `null` if I do `var x = coin as coin;`. The underlying type of the coin object seems to be Node2D even though the Instantiate() method returns a `Node`.

If anyone could shed some light on the hierarchy of what exactly is going on here it'd be appreciated, as resources for C# are incredibly rare.

# Answer
> 1 votes
The problem here was that the root node of the scene was defined as a Node2D, but the script was extending Area2D.

The mismatch meant that godot couldn't incorporate the script into the Node2D, which caused the problem.

Using Rider as the debugging application, the mismatch didn't appear as either an error or a warning within the build output or console. When I ran the project directly within Godot, it appeared as an error in the Debugger output.

Ensuring that the root node of the scene was an Area2D, same as the script, fixed the issue and I was able to cast using this code:

```
var coin = CoinScene.Instantiate<coin>();
AddChild(coin);
coin.someprop = x; // works, coin.cs is the script attached to the root node in my coin scene.

```

---
Tags: c#, godot-4
---


# Question
Title: How do I optimize computations for multiple game objects(>1000)?
It has been 8 months I've been working on my metaball algorithm an the final technique I am trying out is writing magnets to which the sprite mesh edge vertices will update its position to, after finding the closest magnet point.

Code:

```
using HerminkasGams.SpriteSquash;
using UnityEngine;

[System.Serializable]
public class Vertex : MonoBehaviour     // Game object which holds positions of vertex
{
    public Vector3 currentPos;
    public Vector3 initialPos;
    public Vector3 revertingPos;
    [HideInInspector]public GameObject _parentGameObject;
    [HideInInspector]public SpriteMeshModifier _parentSpriteMeshModifier;
    [HideInInspector]public ObjectManagerController _objectManagerController;
    [HideInInspector]public int _index;

    public void SetInitialPos(Vector3 pos, int index, GameObject parentGameObject, SpriteMeshModifier parentSpriteMeshModifier, ObjectManagerController objectManagerController) {

        currentPos = pos;
        initialPos = pos;
        revertingPos = pos;
        _index = index;
        _parentGameObject = parentGameObject;
        _parentSpriteMeshModifier = parentSpriteMeshModifier;
        _objectManagerController = objectManagerController;
    }

    //While this update is necessary, because there are so many verticies, the game is super laggy
    private void Update() {
        //Debug.Log("Update for each slime mesh vertex!");
        if (_objectManagerController.metaballEdgePointVertices.Count > 0) {
            Vector3 nearestMagnetPoint = FindNearestMagnetPoint();
            Debug.Log("Found nearest magnet point for current mesh vertex!");
            Debug.Log(nearestMagnetPoint);
            //UpdateCurrentVertex(nearestMagnetPoint, _index);
        }
    }

    Vector3 FindNearestMagnetPoint() {
        //Compute the nearest metaball edge magnet point by iterating through them if metaballEdgePointVertexGOs is not empty
        if (_objectManagerController.metaballEdgePointVertices.Count > 0) {
            int index = 0;
            //Source, current mesh vertex of slime
            Vector3 scp = _parentSpriteMeshModifier.gameObject.transform.rotation * currentPos;
            Vector3 point = new Vector3(scp.x * _parentSpriteMeshModifier.gameObject.transform.localScale.x, scp.y * _parentSpriteMeshModifier.gameObject.transform.localScale.y, scp.z * _parentSpriteMeshModifier.gameObject.transform.localScale.z) + _parentSpriteMeshModifier.gameObject.transform.position;
            float minDistance = 99999;

            //Will iterate through metaballEdgePointVertexGOs to find closest
            Vector3 scpMagnet = new Vector3(0,0,0);
            Vector3 pointMagnet = new Vector3(0,0,0);
            for (int i = 0; i < _objectManagerController.metaballEdgePointVertices.Count; i++)
            {
                scpMagnet = _objectManagerController.transform.rotation * _objectManagerController.metaballEdgePointVertices[i].currentPos;
                pointMagnet = new Vector3(scpMagnet.x * _objectManagerController.transform.localScale.x, scpMagnet.y * _objectManagerController.transform.localScale.y, scpMagnet.z * _objectManagerController.transform.localScale.z) + _objectManagerController.transform.position;
                var dis = Vector2.Distance(point, pointMagnet);
                if (dis < minDistance)
                {
                    index = i;
                    minDistance = dis;
                }
            }
            return _objectManagerController.metaballEdgePointVertices[index].currentPos;
        }
        return new Vector3(0,0,-1);
    }

    void UpdateCurrentVertex(Vector3 moveTo, int index) {
        _parentSpriteMeshModifier.UpdateVertecies(moveTo, index);
    }
}

```

The problem, as you can see in the image below, is that there are many many vertices for each game object that needs call this logic in its Update(), and it's ridiculously laggy. *Each of these yellow points are what needs to update its position based on how close it is to nearest magnet point.*

I want to stretch these vertices with what is in the Update() logic to hit these magnets points:

Please help me achieve my close to 1 year dream of making color-respecting metaballs...

\*Edit

So I asked Chat GPT the same question and got: Batch Processing: You can reduce the number of Update() calls by creating a manager object that handles the vertex updates in batch. This would be far more efficient than having an Update() method for each vertex GameObject.

So I added the update logic in the parent game object of these vertices.

```
private void Update()
        {
            UpdateMesh();
            foreach (var vertex in vertices)
            {
                if (objectManagerController.metaballEdgePointVertices.Count > 0)
                {
                    // Assume FindNearestMagnetPoint() is now a public method in Vertex
                    // Vector3 nearestMagnetPoint = vertex.FindNearestMagnetPoint();
                    Debug.Log("Current vertex position: ");
                    // Debug.Log(vertex.currentPos);
                    // Debug.Log("Found nearest magnet point for current mesh vertex!");
                    // Debug.Log(nearestMagnetPoint);
                    // Update the vertex position
                    //vertex.UpdateCurrentVertex(nearestMagnetPoint, vertex._index);
                }
            }
        }

```

The problem is, it is still way tooooo laggy. Is there a best solution for my problem?

# Answer
> 0 votes
It would help to optimise the loop, and inside the loop. Some standard rules for this:

1. Dont use .Count in the loop statement (is it slow), cache the .Count to a variable first, e.g.

```
verticesCount = _objectManagerController.metaballEdgePointVertices.Count;
for (int i = 0; i < verticesCount; i++)
```
2. memory allocation is slow, so don't allocate memory in loops, allocate first then assign in loop, so replace the .new and the var dis, like:

```
// assign to x, y, z inside the loop, no new required.
pointMagnet.x = scpMagnet.x * _objectManagerController.transform.localScale.x;
 //.. etc
 dis = Vector2.Distance(point, pointMagnet);
 // where dis is defined outside the loop

```

Also, the debug print inside the loop, will kill performance. The advice on reducing Updates is good. Booth describes significant benefits from doint this: 9. https://medium.com/@jasonbooth\_86226/intro-to-jobs-burst-dod-66c6b81c017f.

# Answer
> 0 votes
I was able to optimize it using ECS and jobs:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Jobs;
using Unity.Collections;
using HerminkasGams.SpriteSquash;
using System.Linq;
using UnityEditor;
using Unity.Burst;
using System.Runtime.Serialization;
using Unity.VisualScripting;

public partial class VertexUpdater : SystemBase
{
    public GameObject ObjectManager;
    public ObjectManagerController objectManagerController;
    [HideInInspector] public List<SpriteMeshModifier> spriteMeshModifiers = new List<SpriteMeshModifier>();
    // [HideInInspector] public List<Vertex> vertices = new List<Vertex>();  // List of vertices; each element of this variable is what I must make magnetic

    private struct VertexCopy {
        public Vector3 currentPos;
        public Vector3 initialPos;
        public Vector3 revertingPos;
        public int _metaballEdgePointCount;

        //_parentSpriteMeshModifier variables:
        public Vector3 _parentSpriteMeshModifierPosition;
        public Quaternion _parentSpriteMeshModifierRotation;
        public Vector3 _parentSpriteMeshModifierLocalscale;

        [HideInInspector]public int _index;
        [HideInInspector]public Vector3 _closestMagnetPoint;

        public VertexCopy(Vector3 pos, int index, int metaballEdgePointCount, Vector3 parentSpriteMeshModifierPosition, Quaternion parentSpriteMeshModifierRotation, Vector3 parentSpriteMeshModifierLocalscale, Vector3 closestMagnetPoint) {
            currentPos = pos;
            initialPos = pos;
            revertingPos = pos;
            _index = index;
            _metaballEdgePointCount = metaballEdgePointCount;
            //_parentSpriteMeshModifierPosition variables
            _parentSpriteMeshModifierPosition = parentSpriteMeshModifierPosition;
            _parentSpriteMeshModifierRotation = parentSpriteMeshModifierRotation;
            _parentSpriteMeshModifierLocalscale = parentSpriteMeshModifierLocalscale;
            _closestMagnetPoint = closestMagnetPoint;
        }

        public (Vector3, float) FindNearestMagnetPoint(NativeArray<Vector3> metaballVertexPositionArray) {
            float minDistanceUnaltered = 99999;
            //Compute the nearest metaball edge magnet point by iterating through them if metaballEdgePointVertexGOs is not empty
            if (_metaballEdgePointCount > 0) {
                int index = 0;
                Vector3 scp = _parentSpriteMeshModifierRotation * currentPos;
                Vector3 point = new Vector3(scp.x * _parentSpriteMeshModifierLocalscale.x, scp.y * _parentSpriteMeshModifierLocalscale.y, scp.z * _parentSpriteMeshModifierLocalscale.z) + _parentSpriteMeshModifierPosition;

                float minDistance = 99999;

                //Will iterate through metaballEdgePointVertexGOs to find closest
                //Vector3 scpMagnet = new Vector3(0,0,0);
                for (int i = 0; i < _metaballEdgePointCount; i++)
                {
                    var dis = Vector2.Distance(point, metaballVertexPositionArray[i]);
                    if (dis < minDistance)
                    {
                        index = i;
                        minDistance = dis;
                    }
                }

                //Invert metaballVertexPositionArray[index] back to vertex coordinates
                Vector3 vec1 = metaballVertexPositionArray[index] - _parentSpriteMeshModifierPosition;
                Vector3 vec2 = _parentSpriteMeshModifierLocalscale;
                Vector3 result = new Vector3(vec1.x / vec2.x, vec1.y / vec2.y, vec1.z / vec2.z);
                Vector3 scpLocal = Quaternion.Inverse(_parentSpriteMeshModifierRotation) * (result);
                // Debug.Log(currentPos);
                return (scpLocal, minDistance);
            }
            return (new Vector3(0,0,-1), minDistanceUnaltered);
        }
    }

    [BurstCompile]
    private struct ComputeJob : IJobFor {
        [NativeDisableParallelForRestriction]
        public NativeArray<VertexCopy> vertexCopyArray;
        [ReadOnly]
        public NativeArray<Vector3> metaballVertexPositionArray;

        public void Execute(int index) {
            VertexCopy vertexCopy = this.vertexCopyArray[index];
            float minDistance = 9999;
            (vertexCopy._closestMagnetPoint, minDistance) = vertexCopy.FindNearestMagnetPoint(metaballVertexPositionArray);
            //If closest distance is less than threshold
            if (minDistance < 0.2) {
                vertexCopy.currentPos = vertexCopy._closestMagnetPoint;
                this.vertexCopyArray[index] = vertexCopy;
            }
        }
    }

    protected override void OnStartRunning()
    {
        ObjectManager = GameObject.Find("ObjectManager");
        objectManagerController = ObjectManager.GetComponent<ObjectManagerController>();
        // GameObject.Find("SpriteMeshModifier");
        // EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
        // // Create an Entity "archetype" that will have MyComponent
        // EntityArchetype spriteMeshModifierArchetype = entityManager.CreateArchetype(typeof(SpriteMeshModifier));
        // // Create an entity with that archetype
        // Entity spriteMeshModifierEntity = entityManager.CreateEntity(spriteMeshModifierArchetype);

        List<GameObject> waterslimesDisplay = objectManagerController.colorSlimesDisplayGlobal;
        foreach (GameObject waterslimeDisplay in waterslimesDisplay) {
            spriteMeshModifiers.Add(waterslimeDisplay.GetComponent<SpriteMeshModifier>());
        }
        base.OnStartRunning();
    }

    protected override void OnUpdate()
    {
        CallJobs();
        //throw new System.NotImplementedException();
    }

    private void CallJobs() {
        foreach (SpriteMeshModifier spriteMeshModifier in spriteMeshModifiers) {
            if(spriteMeshModifier.vertices.Count > 0 && spriteMeshModifier._isRegenerated && spriteMeshModifier.objectManagerController.metaballEdgePointVertices.Count > 0) {
                NativeArray<VertexCopy> vertexCopies = new NativeArray<VertexCopy>(spriteMeshModifier.vertices.Count, Allocator.TempJob);
                NativeArray<Vector3> metaballVertexPositions = new NativeArray<Vector3>(spriteMeshModifier.objectManagerController.metaballEdgePointVertices.Count, Allocator.TempJob);
                CopyThingsTo(ref vertexCopies, ref metaballVertexPositions, spriteMeshModifier);
                // Do heavy computation in a job
                ComputeJob job = new ComputeJob() {
                    vertexCopyArray = vertexCopies,
                    metaballVertexPositionArray = metaballVertexPositions
                };
                job.ScheduleParallel(vertexCopies.Length, 64, default).Complete();
                AssignComputedValues(vertexCopies, spriteMeshModifier);
                UpdatePositions(vertexCopies, spriteMeshModifier);
                // Don't forget to dispose
                vertexCopies.Dispose();
                metaballVertexPositions.Dispose();
            }
        }
    }

    private void CopyThingsTo(ref NativeArray<VertexCopy> copiesArray, ref NativeArray<Vector3> metaballVertexPositionsArray, SpriteMeshModifier spriteMeshModifier) {
        for (int i = 0; i < spriteMeshModifier.vertices.Count; i++) {
            Vertex vertex = spriteMeshModifier.vertices[i];
            copiesArray[i] = new VertexCopy(vertex.currentPos, i, vertex._objectManagerController.metaballEdgePointVertices.Count, vertex._parentSpriteMeshModifier.transform.parent.gameObject.transform.position, vertex._parentSpriteMeshModifier.gameObject.transform.rotation, vertex._parentSpriteMeshModifier.gameObject.transform.localScale, vertex._closestMagnetPoint);
        }
        for (int i = 0; i < spriteMeshModifier.objectManagerController.metaballEdgePointVertices.Count; i++) {
            MetaballEdgePointVertex metaballEdgePointVertex = spriteMeshModifier.objectManagerController.metaballEdgePointVertices[i];
            metaballVertexPositionsArray[i] = metaballEdgePointVertex.currentPos;
        }
    }

    private void AssignComputedValues(in NativeArray<VertexCopy> copiesArray, SpriteMeshModifier spriteMeshModifier) {
        for (int i = 0; i < spriteMeshModifier.vertices.Count; ++i) {
            spriteMeshModifier.vertices[i]._closestMagnetPoint = copiesArray[i]._closestMagnetPoint;
        }
    }

    private void UpdatePositions(in NativeArray<VertexCopy> copiesArray, SpriteMeshModifier spriteMeshModifier) {
        for (int i = 0; i < spriteMeshModifier.vertices.Count; ++i) {
            if(copiesArray[i].currentPos == copiesArray[i]._closestMagnetPoint) {
                //Should I lerp between copiesArray[i]._closestMagnetPoint and copiesArray[i].initialPos?
                spriteMeshModifier.vertices[i].UpdateCurrentVertex(copiesArray[i]._closestMagnetPoint, copiesArray[i]._index);
            }
            else {
                spriteMeshModifier.ResetPositionOfSelectedVertex(copiesArray[i]._index);
                spriteMeshModifier.UpdateMesh();
            }
        }
    }
}

```

I still hate the way my metaball effect looks, however...

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


# Question
Title: How do I properly use Entities and ECS in a current project that uses MonoBehavior?
I have a class called SpriteMeshModifier, which is a MonoBehavior. Since the rest of my script depends on this class being a MonoBehavior, I have trouble deciding how to translate the bulky updating logic for vertices into an ECS Entity. Chat GPT mentioned that I should "MonoBehaviour Logic: Since we are moving to ECS, the logic in your Vertex MonoBehaviour should be transferred to ECS Systems. Make sure to disable or remove the MonoBehaviour scripts to avoid duplicate logic." Thus, I am having trouble how to integrate this tutorial: https://coffeebraingames.wordpress.com/2021/11/23/the-safest-way-to-use-dots-in-your-monobehaviour-project/ How should I go about it?

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

namespace HerminkasGams.SpriteSquash
{
    [System.Serializable]
    public class SpriteMeshModifier : MonoBehaviour
    {
        public Sprite _sprite;
        public Material material;
        public GameObject Vertex;
        public GameObject ObjectManager;
        [HideInInspector]public ObjectManagerController objectManagerController;

        [HideInInspector]
        public Color Color;          // Colour of material

        [HideInInspector]
        public int sortingLayerID;   // Sorting layer of mesh renderer

        [HideInInspector]
        public int sortingOrder;     // Sorting order of mesh renderer

        [HideInInspector]
        public float refine = 0.5f;  // Refine defines how dense will be created mesh
        [HideInInspector]
        public float forceImpact;   // Force impact is how strong is selected vertex impacting other vertices
        [HideInInspector]
        public float sizeImpact;    // Size impact is radius around selected vertex, this radius is selecting vertices which will be imacted
        [HideInInspector]
        public float stiffnes = 1;  // Defines how vertices are stiff - in other words how fast they can get to their initial position
        [HideInInspector]
        public float revert = 1;    // Revert is amount in lerp function to initial state of mesh

        [HideInInspector]
        public List<KeyValuePair<int, int>> trianglesLines = new List<KeyValuePair<int, int>>();    // Lines holding triangles's lines

        [HideInInspector]
        public bool _isCustomShape;   // Button holds whether generated mesh is customed

        [HideInInspector]
        public bool _isSelfRestoring; // Self restoring mesh is that vertices are returning to their initial state

        [HideInInspector]
        public List<Vertex> vertices = new List<Vertex>();  // List of vertices; each element of this variable is what I must make magnetic

        public float HandleRadious; // Handle radious

        public void Awake() {
            // _sprite = gameObject.GetComponent<SoftSprite>().Sprite;
            //Search starts from Resources folder
            // Vertex = Resources.Load<GameObject>( "../Herminka's gams/Prefabs/Vertex" );
            ObjectManager = GameObject.Find("ObjectManager");
            objectManagerController = ObjectManager.GetComponent<ObjectManagerController>();
        }

        private void Update()
        {
            UpdateMesh();
            foreach (var vertex in vertices)
            {
                if (objectManagerController.metaballEdgePointVertices.Count > 0)
                {
                    // Assume FindNearestMagnetPoint() is now a public method in Vertex
                    //Vector3 nearestMagnetPoint = vertex.FindNearestMagnetPoint();
                    Debug.Log("Current vertex position: ");
                    // Debug.Log(vertex.currentPos);
                    // Debug.Log("Found nearest magnet point for current mesh vertex!");
                    // Debug.Log(nearestMagnetPoint);
                    // Update the vertex position
                    //vertex.UpdateCurrentVertex(nearestMagnetPoint, vertex._index);
                }
            }
        }

        private void AssignMesh(IMesh meshGenerator)    // Generates and assignes mesh to mesh filter
        {

            GetComponent<MeshFilter>().sharedMesh = meshGenerator.GenerateMesh();
           GetComponent<MeshRenderer>().sharedMaterial = new Material(material);
            GetComponent<MeshRenderer>().sharedMaterial.mainTexture = _sprite.texture;

        }

        private void GenerateVerteciesList()             // Generates and initialises vertices
        {
            foreach (var item in GetComponentsInChildren<Vertex>())
            {
                DestroyImmediate(item.gameObject);
            }
            vertices.Clear();

            int cntr = 0;
            float circleColliderRadius = 10.0f;

            foreach (var vertex in GetComponent<MeshFilter>().sharedMesh.vertices.ToList())
            {
                var go = Instantiate(Vertex, transform);
                go.name = go.name + " " + cntr;

                // Add CircleCollider2D
                CircleCollider2D circleCollider = go.AddComponent<CircleCollider2D>();
                // Configure CircleCollider2D properties
                circleCollider.radius = circleColliderRadius;
                circleCollider.isTrigger = true;

                // Rigidbody2D rigidbody2D = go.AddComponent<Rigidbody2D>();
                // rigidbody2D.gravityScale = 0;

                var ver = go.GetComponent<Vertex>();
                ver.SetInitialPos(vertex, cntr, go, this, objectManagerController); //this is reference to SpriteMeshModifier object that owns vertices
                vertices.Add(ver);
                cntr++;
            }
        }

        public void UpdateMesh()                        // Updates Mesh
        {
            Mesh mesh = GetComponent<MeshFilter>().sharedMesh;
            mesh.vertices = vertices.Select(x => x.currentPos).ToArray();
            GetComponent<MeshFilter>().sharedMesh = mesh;
        }

        public void ExtractMeshLines()                  // Extract lines from mesh, so it can be displayed in scene view
        {
            List<string> edges = new List<string>();
            trianglesLines.Clear();
            int[] triangles = GetComponent<MeshFilter>().sharedMesh.triangles;

            for (int i = 0; i < triangles.Length; i += 3)
            {
                for (int e = 0; e < 3; e++)
                {
                    int vert1 = triangles[i + e];
                    int vert2 = triangles[i + e + 1 > i + 2 ? i : i + e + 1];
                    string edge = Mathf.Min(vert1, vert2) + ":" + Mathf.Max(vert1, vert2);
                    if (!edges.Contains(edge))
                    {
                        edges.Add(edge);
                        trianglesLines.Add(new KeyValuePair<int, int>(vert1, vert2));
                    }
                }
            }
        }

        public void UpdateVertecies(Vector3 moveTo, int index)    //  Update vertices
        {
            moveTo = Quaternion.Inverse(transform.rotation) * moveTo;
            Vector3 newMousePosition = new Vector3(moveTo.x / transform.localScale.x, moveTo.y / transform.localScale.y, moveTo.z / transform.localScale.z)
                  - Quaternion.Inverse(transform.rotation) * new Vector3(transform.position.x / transform.localScale.x, transform.position.y / transform.localScale.y, transform.position.z / transform.localScale.z);

            UpdatePositionOfVertices(moveTo, newMousePosition - vertices[index].currentPos);
            UpdatePositionOfSelectedVertex(index, newMousePosition);
            UpdateMeshFromEditor();
        }

        private void UpdatePositionOfSelectedVertex(int index, Vector3 pos) // Update position of selected vertex
        {
            vertices[index].currentPos = pos;
        }

        private void UpdatePositionOfVertices(Vector3 mousePosition, Vector3 direction) // Update position of all vertices
        {
            for (int i = 0; i < vertices.Count; i++)
            {
                Vector3 scp = transform.rotation * vertices[i].currentPos;
                Vector3 vertexPoint = new Vector3(scp.x * transform.localScale.x, scp.y * transform.localScale.y, scp.z * transform.localScale.z) + transform.position;
                var dis = Vector2.Distance(mousePosition, vertexPoint);
                float force;
                if (dis <= sizeImpact)
                {
                    force = Mathf.Clamp((Mathf.Abs((dis - sizeImpact) / sizeImpact) - 1.0f + 2 * forceImpact), 0, 1);
                    vertices[i].currentPos = vertices[i].currentPos + direction * force;
                }
                else
                {
                    if (_isSelfRestoring)
                    {
                        dis = Vector2.Distance(vertices[i].currentPos, vertices[i].initialPos);
                        var dis2 = Vector2.Distance(mousePosition, vertices[i].initialPos);
                        force = Mathf.Clamp(dis * dis2, 0, stiffnes * 1);
                        vertices[i].currentPos = vertices[i].currentPos + (vertices[i].initialPos - vertices[i].currentPos) * force;
                    }
                }
            }
        }

        public void UpdateRevertedPositionsOfVertices() {       // Update reverted position of vertices

            foreach (var item in vertices)
            {
                item.revertingPos = item.currentPos;
            }
            revert = 1;
        }

        public void Regenerate()                                        // Regenerates mesh
        {
            if (_isCustomShape)
            {
                AssignMesh(new CustomMesh(_sprite, refine));
            }
            else
            {
                AssignMesh(new RegularMesh(_sprite));
            }
            GenerateVerteciesList();
            ExtractMeshLines();
        }

        public void Reset()                                             // Resets mesh
        {
            foreach (var item in vertices)
            {
                item.currentPos = item.initialPos;
            }
            UpdateRevertedPositionsOfVertices();
            UpdateMesh();
        }

        private void UpdateMeshFromEditor()                              // Update mesh when not in play mode
        {
            if (Application.isEditor)
            {
                UpdateMesh();
            }
        }

        public void Revert(float slider)                                // Reverts position of meshes
        {
            foreach (var item in vertices)
            {
                item.currentPos = Vector3.Lerp(item.initialPos, item.revertingPos, slider);
            }
            UpdateMeshFromEditor();
        }

        public int GetIndexAtPosition(Vector3 pos) {

            int index = 0;
            Vector3 scp = transform.rotation * vertices[0].currentPos;
            Vector3 point = new Vector3(scp.x * transform.localScale.x, scp.y * transform.localScale.y, scp.z * transform.localScale.z) + transform.position;

            float minDistance = Vector2.Distance(pos, point);

            for (int i = 0; i < vertices.Count; i++)
            {
                scp = transform.rotation * vertices[i].currentPos;
                point = new Vector3(scp.x * transform.localScale.x, scp.y * transform.localScale.y, scp.z * transform.localScale.z) + transform.position;
                var dis = Vector2.Distance(pos, point);
                if (dis < minDistance)
                {
                    index = i;
                    minDistance = dis;
                }
            }
            //Debug.Log(index);
            return index;
        }

        public void SetSortingOrder(int sortingOrdr)
        {
           GetComponent<MeshRenderer>().sortingOrder = sortingOrdr;
           sortingOrder = sortingOrdr;
        }

        public void SetSortingLayerID(int newId)
        {
            GetComponent<MeshRenderer>().sortingLayerID = newId;
            sortingLayerID = newId;
        }

        public void SetNewColor(Color col) {
            GetComponent<MeshRenderer>().material.color = col;
        }
    }
}

```

The actual part of Update I want to translate to ECS is:

```
foreach (var vertex in vertices)
            {
                if (objectManagerController.metaballEdgePointVertices.Count > 0)
                {
                    // Assume FindNearestMagnetPoint() is now a public method in Vertex
                    Vector3 nearestMagnetPoint = vertex.FindNearestMagnetPoint();
                    //Debug.Log("Current vertex position: ");
                    // Debug.Log(vertex.currentPos);
                    // Debug.Log("Found nearest magnet point for current mesh vertex!");
                    // Debug.Log(nearestMagnetPoint);
                    // Update the vertex position
                    //vertex.UpdateCurrentVertex(nearestMagnetPoint, vertex._index);
                }
            }

```

of

private void Update()
        {
            UpdateMesh();
            foreach (var vertex in vertices)
            {
                if (objectManagerController.metaballEdgePointVertices.Count > 0)
                {
                    // Assume FindNearestMagnetPoint() is now a public method in Vertex
                    Vector3 nearestMagnetPoint = vertex.FindNearestMagnetPoint();
                    //Debug.Log("Current vertex position: ");
                    // Debug.Log(vertex.currentPos);
                    // Debug.Log("Found nearest magnet point for current mesh vertex!");
                    // Debug.Log(nearestMagnetPoint);
                    // Update the vertex position
                    //vertex.UpdateCurrentVertex(nearestMagnetPoint, vertex._index);
                }
            }
        }
```
</code></pre>

# Answer
> 0 votes
I was able to optimize it using ECS and jobs:

<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Jobs;
using Unity.Collections;
using HerminkasGams.SpriteSquash;
using System.Linq;
using UnityEditor;
using Unity.Burst;
using System.Runtime.Serialization;
using Unity.VisualScripting;

public partial class VertexUpdater : SystemBase
{
    public GameObject ObjectManager;
    public ObjectManagerController objectManagerController;
    [HideInInspector] public List<SpriteMeshModifier> spriteMeshModifiers = new List<SpriteMeshModifier>();
    // [HideInInspector] public List<Vertex> vertices = new List<Vertex>();  // List of vertices; each element of this variable is what I must make magnetic

    private struct VertexCopy {
        public Vector3 currentPos;
        public Vector3 initialPos;
        public Vector3 revertingPos;
        public int _metaballEdgePointCount;

        //_parentSpriteMeshModifier variables:
        public Vector3 _parentSpriteMeshModifierPosition;
        public Quaternion _parentSpriteMeshModifierRotation;
        public Vector3 _parentSpriteMeshModifierLocalscale;

        [HideInInspector]public int _index;
        [HideInInspector]public Vector3 _closestMagnetPoint;

        public VertexCopy(Vector3 pos, int index, int metaballEdgePointCount, Vector3 parentSpriteMeshModifierPosition, Quaternion parentSpriteMeshModifierRotation, Vector3 parentSpriteMeshModifierLocalscale, Vector3 closestMagnetPoint) {
            currentPos = pos;
            initialPos = pos;
            revertingPos = pos;
            _index = index;
            _metaballEdgePointCount = metaballEdgePointCount;
            //_parentSpriteMeshModifierPosition variables
            _parentSpriteMeshModifierPosition = parentSpriteMeshModifierPosition;
            _parentSpriteMeshModifierRotation = parentSpriteMeshModifierRotation;
            _parentSpriteMeshModifierLocalscale = parentSpriteMeshModifierLocalscale;
            _closestMagnetPoint = closestMagnetPoint;
        }

        public (Vector3, float) FindNearestMagnetPoint(NativeArray<Vector3> metaballVertexPositionArray) {
            float minDistanceUnaltered = 99999;
            //Compute the nearest metaball edge magnet point by iterating through them if metaballEdgePointVertexGOs is not empty
            if (_metaballEdgePointCount > 0) {
                int index = 0;
                Vector3 scp = _parentSpriteMeshModifierRotation * currentPos;
                Vector3 point = new Vector3(scp.x * _parentSpriteMeshModifierLocalscale.x, scp.y * _parentSpriteMeshModifierLocalscale.y, scp.z * _parentSpriteMeshModifierLocalscale.z) + _parentSpriteMeshModifierPosition;

                float minDistance = 99999;

                //Will iterate through metaballEdgePointVertexGOs to find closest
                //Vector3 scpMagnet = new Vector3(0,0,0);
                for (int i = 0; i < _metaballEdgePointCount; i++)
                {
                    var dis = Vector2.Distance(point, metaballVertexPositionArray[i]);
                    if (dis < minDistance)
                    {
                        index = i;
                        minDistance = dis;
                    }
                }

                //Invert metaballVertexPositionArray[index] back to vertex coordinates
                Vector3 vec1 = metaballVertexPositionArray[index] - _parentSpriteMeshModifierPosition;
                Vector3 vec2 = _parentSpriteMeshModifierLocalscale;
                Vector3 result = new Vector3(vec1.x / vec2.x, vec1.y / vec2.y, vec1.z / vec2.z);
                Vector3 scpLocal = Quaternion.Inverse(_parentSpriteMeshModifierRotation) * (result);
                // Debug.Log(currentPos);
                return (scpLocal, minDistance);
            }
            return (new Vector3(0,0,-1), minDistanceUnaltered);
        }
    }

    [BurstCompile]
    private struct ComputeJob : IJobFor {
        [NativeDisableParallelForRestriction]
        public NativeArray<VertexCopy> vertexCopyArray;
        [ReadOnly]
        public NativeArray<Vector3> metaballVertexPositionArray;

        public void Execute(int index) {
            VertexCopy vertexCopy = this.vertexCopyArray[index];
            float minDistance = 9999;
            (vertexCopy._closestMagnetPoint, minDistance) = vertexCopy.FindNearestMagnetPoint(metaballVertexPositionArray);
            //If closest distance is less than threshold
            if (minDistance < 0.2) {
                vertexCopy.currentPos = vertexCopy._closestMagnetPoint;
                this.vertexCopyArray[index] = vertexCopy;
            }
        }
    }

    protected override void OnStartRunning()
    {
        ObjectManager = GameObject.Find("ObjectManager");
        objectManagerController = ObjectManager.GetComponent<ObjectManagerController>();
        // GameObject.Find("SpriteMeshModifier");
        // EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
        // // Create an Entity "archetype" that will have MyComponent
        // EntityArchetype spriteMeshModifierArchetype = entityManager.CreateArchetype(typeof(SpriteMeshModifier));
        // // Create an entity with that archetype
        // Entity spriteMeshModifierEntity = entityManager.CreateEntity(spriteMeshModifierArchetype);

        List<GameObject> waterslimesDisplay = objectManagerController.colorSlimesDisplayGlobal;
        foreach (GameObject waterslimeDisplay in waterslimesDisplay) {
            spriteMeshModifiers.Add(waterslimeDisplay.GetComponent<SpriteMeshModifier>());
        }
        base.OnStartRunning();
    }

    protected override void OnUpdate()
    {
        CallJobs();
        //throw new System.NotImplementedException();
    }

    private void CallJobs() {
        foreach (SpriteMeshModifier spriteMeshModifier in spriteMeshModifiers) {
            if(spriteMeshModifier.vertices.Count > 0 && spriteMeshModifier._isRegenerated && spriteMeshModifier.objectManagerController.metaballEdgePointVertices.Count > 0) {
                NativeArray<VertexCopy> vertexCopies = new NativeArray<VertexCopy>(spriteMeshModifier.vertices.Count, Allocator.TempJob);
                NativeArray<Vector3> metaballVertexPositions = new NativeArray<Vector3>(spriteMeshModifier.objectManagerController.metaballEdgePointVertices.Count, Allocator.TempJob);
                CopyThingsTo(ref vertexCopies, ref metaballVertexPositions, spriteMeshModifier);
                // Do heavy computation in a job
                ComputeJob job = new ComputeJob() {
                    vertexCopyArray = vertexCopies,
                    metaballVertexPositionArray = metaballVertexPositions
                };
                job.ScheduleParallel(vertexCopies.Length, 64, default).Complete();
                AssignComputedValues(vertexCopies, spriteMeshModifier);
                UpdatePositions(vertexCopies, spriteMeshModifier);
                // Don't forget to dispose
                vertexCopies.Dispose();
                metaballVertexPositions.Dispose();
            }
        }
    }

    private void CopyThingsTo(ref NativeArray<VertexCopy> copiesArray, ref NativeArray<Vector3> metaballVertexPositionsArray, SpriteMeshModifier spriteMeshModifier) {
        for (int i = 0; i < spriteMeshModifier.vertices.Count; i++) {
            Vertex vertex = spriteMeshModifier.vertices[i];
            copiesArray[i] = new VertexCopy(vertex.currentPos, i, vertex._objectManagerController.metaballEdgePointVertices.Count, vertex._parentSpriteMeshModifier.transform.parent.gameObject.transform.position, vertex._parentSpriteMeshModifier.gameObject.transform.rotation, vertex._parentSpriteMeshModifier.gameObject.transform.localScale, vertex._closestMagnetPoint);
        }
        for (int i = 0; i < spriteMeshModifier.objectManagerController.metaballEdgePointVertices.Count; i++) {
            MetaballEdgePointVertex metaballEdgePointVertex = spriteMeshModifier.objectManagerController.metaballEdgePointVertices[i];
            metaballVertexPositionsArray[i] = metaballEdgePointVertex.currentPos;
        }
    }

    private void AssignComputedValues(in NativeArray<VertexCopy> copiesArray, SpriteMeshModifier spriteMeshModifier) {
        for (int i = 0; i < spriteMeshModifier.vertices.Count; ++i) {
            spriteMeshModifier.vertices[i]._closestMagnetPoint = copiesArray[i]._closestMagnetPoint;
        }
    }

    private void UpdatePositions(in NativeArray<VertexCopy> copiesArray, SpriteMeshModifier spriteMeshModifier) {
        for (int i = 0; i < spriteMeshModifier.vertices.Count; ++i) {
            if(copiesArray[i].currentPos == copiesArray[i]._closestMagnetPoint) {
                //Should I lerp between copiesArray[i]._closestMagnetPoint and copiesArray[i].initialPos?
                spriteMeshModifier.vertices[i].UpdateCurrentVertex(copiesArray[i]._closestMagnetPoint, copiesArray[i]._index);
            }
            else {
                spriteMeshModifier.ResetPositionOfSelectedVertex(copiesArray[i]._index);
                spriteMeshModifier.UpdateMesh();
            }
        }
    }
}
```

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


# Question
Title: How to fill the rest of the viewport with a Phaser game's content?
In Phaser, is it possible to fill the remaining part of the Browser window with the game's (clipped) content, and still keep the aspect ratio of the game intact?

For example, I have a game which is 490x844px, and all of the elements in the game are positioned according to those coordinates and size. I also use the following scaling properties on the game

```
scale: {
  mode: Phaser.Scale.FIT,
  autoCenter: Phaser.Scale.CENTER_BOTH,
},

```

However, I still have some game elements exceeding the game area, and are clipped off. I want to display this content if we have some space left in the Browser window. Is this possible?

I tried to use `game.scale.setGameSize(1600, 1200);` and then change the camera's viewport to center the game again (e.g. `cameras.main.setViewport(offsetX, offsetY, this.scale.width, this.scale.height)`.) It does work, but only makes the "clipped" content on right side of the game appear. The left side of the game is still clipped and not visible. I want to make the left side AND the right side of the game's content to appear on screen, not just the right part.

Maybe the example image will make it more clear what my problem is, and what I want to achieve. Any help or pointers are appreciated.

# Answer
> 1 votes
I think I found a solution that kind of works. I don't think it's the best, and I'm still curious if you have alternatives.

I set the scale config of the game to:

```
scale: {
  mode: Phaser.Scale.HEIGHT_CONTROLS_WIDTH,
  autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
},

```

I then adjust the game-size with the following code after initializing the game.

```
this.game.scale.setGameSize(window.innerWidth, GAME_HEIGHT);

```

Then, in a scene, I change the viewport bounds:

```
scene.cameras.main.setBounds(
  - scene.cameras.main.width / 2 + GAME_WIDTH / 2,
  0,
  GAME_WIDTH,
  GAME_HEIGHT
);

```

I also need to re-scale the game when the viewport changes size (width or height.) With this, I'm not clipping the game on the left side anymore.

---
Tags: phaser
---


# Question
Title: Space control nodes evenly in a container in Godot
Is it possible to achieve this behavior with a container in Godot?

To explain in more details, the black box is the hypothetical container I'm looking for and the red boxes are children control nodes: the children control nodes are evenly distributed in the container, starting from the very left and ending at the very right.

I already looked at the GridContainer, and while I can get close by playing with the size flags of the children control nodes, this isn't exactly the behavior I described.

My question is only whether this is possible with the default nodes provided by Godot. I'm not asking how to create a Godot scene with this behavior.

I'm using the new Godot 4 if that makes any difference.

# Answer
The solution to your example is to create empty Controls, we'll call them "Spacer"s, with their horizontal container sizing set to **fill** and **expand** placing them in between the visual nodes.

Here is an example scene tree:

```
HBoxContainer
- RedSquare1
- Spacer1
- RedSquare2
- Spacer2
- RedSquare3

```

You can play around with this composition and the various sizing settings. For example, you can have the first leading RedSquare1, a space, then the remaining RedSquare's right aligned by simply removing Spacer2.

Another point of flexibility is to adjust the Spacer's **Stretch Ratio**. You can have one spacer take up the specified ratio compared to the other nodes.

This layout model is very similar to CSS's FlexBox model. Where we have the flex container and the items are the child nodes.

Hope this helps.
> 3 votes

# Answer
Not sure why nobody mentioned this yet, but this functionality is available under Theme Overrides \> Constants \> Separation on Hbox, Hflow, etc. Containers:
> 3 votes

---
Tags: gui, godot-4
---


# Question
Title: How can I check if `call`, `callv` failed
In Godot, how can I check whether e.g. `Call(...)` or `Callv(...)` succeeded or failed?

By failed I mean due to e.g. missing method, wrong number of arguments, etc., not because of the method itself failing or returning an error. This API returns `Variant`, not `Error` and, if I'm not mistaken, it just returns null on failure (and logs an error). How can I at runtime differentiate that from a successful `void` or `null` result, "catching" that an error happened?

My question is mainly for C#, but I'd like to know that for GDScript too.

# Answer
## Checking a method signature with reflection

I believe Godot does not have a means to check if a call failed...

But you can check your concerns before making the call.

If you are going to call like this:

```
obj.call(method_name)

```

You can check if `obj` has that method like this:

```
if obj.has_method(method_name):
    obj.call(method_name)

```

Checking the number of parameters takes more effort, for example:

```
if has_method(method_name):
    var parameter_count := 0
    for method in obj.get_method_list():
        if method["name"] != method_name:
            continue

        var parameters:Array = method["args"]
        parameter_count = parameters.size()
        break

    if parameter_count == 3:
        obj.call(method_name, arg1, arg2, arg3)

```

If you also want to check the types, well:

```
var method_name := "my_method"
var signature := [TYPE_INT, TYPE_STRING]
var valid := false

for method in obj.get_method_list():
    if method["name"] != method_name:
        continue

    valid = true
    var parameters:Array = method["args"]
    if signature.size() != parameters.size():
        valid = false
        break

    for index in parameters.size():
        if parameters[index]["type"] != signature[index]:
            valid = false
            break

    break

if valid:
    obj.call(method_name, 123, "abc")

```

Oh, you want to check the class too? Hmm...

```
var method_name := "my_method"
var signature := [TYPE_INT, TYPE_STRING, "Node"]
var valid := false

for method in obj.get_method_list():
    if method["name"] != method_name:
        continue

    valid = true
    var parameters:Array = method["args"]
    if signature.size() != parameters.size():
        valid = false
        break

    for index in parameters.size():
        var expected = signature[index]
        if typeof(expected) == TYPE_STRING:
            if parameters[index]["class_name"] != expected:
                valid = false
                break

        else:
            if parameters[index]["type"] != expected:
                valid = false
                break

    break

if valid:
    obj.call(method_name, 123, "abc", self)

```

I presume you might want to encapsulate this for ease of reuse, but I'll leave that to you.

---

## Checking with code generation

When would this be useful?

* You are writing some generic code, duck typing, etc.

This is bound to what you write, and to code under your control, so you should be able to remove any possible errors.

Presumably you test your game and identify and fix any problems, so this won't happen in runtime. And no, Godot won't chance versions underneath you (much less in runtime).
* It might be useful to interface with code beyond your control. For example, if you are making an addon/plugin that calls into other game code yet to be written.

In this case, I'd believe the underlying problem is the lack of interfaces/contracts in GDScript. Current plan for GDScript is that it will have traits.

I submit to your consideration using a signal bus. The signal bus will be a global object that both caller and called have access to. So the caller can emit the signal, and the called connect to the signal... Without the caller and called knowing each other. This gives you fully decoupled code.

For C# in particular, you do have interfaces, so you can define an interface and have the other code implement it.
* You are doing code generation. And that is what I'll tackle here.

You can generate and run code in runtime in Godot two ways:

* Create an `Script` object.
* Create an `Expression` object.

---

**Script**

I'll create a new `GDScript` object:

```
var my_runtuime_script:= GDScript.new()

```

I need to set its source code, which will be some string with whatever code I need, generated by whatever means I have (I'm using a multiline `String` literal here):

```
var my_runtuime_script:= GDScript.new()
my_runtuime_script.source_code = """
func my_generated_func() -> void:
    prints("hello generated world")
"""

```

And then I need to reload it:

```
var my_runtuime_script:= GDScript.new()
my_runtuime_script.source_code = """
func my_generated_func() -> void:
    prints("hello generated world")
"""
my_runtuime_script.reload()

```

And `reload` will report errors! So if you have a syntax error, you find out here:

```
var my_runtuime_script:= GDScript.new()
my_runtuime_script.source_code = """
func my_generated_func() -> void:
    prints("hello generated world")
"""
var err := my_runtuime_script.reload()
prints(err)

```

Assuming everything is OK, we can instantiate the script and call into it:

```
var my_runtuime_script:= GDScript.new()
my_runtuime_script.source_code = """
func my_generated_func() -> void:
    prints("hello generated world")
"""
var err := my_runtuime_script.reload()
prints(err)
if err == OK:
    var instance:Object = my_runtuime_script.new()
    instance.call("my_generated_func")

```

Output:

```
0
hello generated world

```

Here the `0` means no error (`OK`), and `hello generated world` is the output form the function created at runtime.

---

**Expression**

Again we start by creating an object, this time the class is `Expression`:

```
var expression := Expression.new()

```

And we have to give it the code, which has to be an expression. We can define parameters, for example:

```
var expression := Expression.new()
var parameters := PackedStringArray(["p"])
expression.parse("2 + p", parameters)

```

And `parse` returns! So we get any parse errors here:

```
var expression := Expression.new()
var parameters := PackedStringArray(["p"])
var parse_err := expression.parse("2 + p", parameters)

```

If there was a parse error, we can call `get_error_text`:

```
var expression := Expression.new()
var parameters := PackedStringArray(["p"])
var parse_err := expression.parse("2 + p", parameters)
if parse_err != OK:
    push_error(expression.get_error_text())

```

Then to execute it, we need to pass the arguments for the parameters we defined:

```
var expression := Expression.new()
var parameters := PackedStringArray(["p"])
var parse_err := expression.parse("2 + p", parameters)
if parse_err != OK:
    push_error(expression.get_error_text())
else:
    var arguments := [5]
    var result = expression.execute(arguments, null, true)

```

Here the `null` is the "self" reference (the instance on which the expression will be executed), and `true` means we do not want it to show errors... We will handle them!

How do we handle them? Like this:

```
var expression := Expression.new()
var parameters := PackedStringArray(["p"])
var parse_err := expression.parse("2 + p", parameters)
if parse_err != OK:
    push_error(expression.get_error_text())
else:
    var arguments := [5]
    var result = expression.execute(arguments, null, true)
    if expression.has_execute_failed():
        push_error(expression.get_error_text())
    else:
        print(result)

```

output:

```
7

```

*This is 2 + 5*

And we can leverage this to make a call:

```
var method_name := "my_method"
var method_arguments := [123, "abc"]

var expression := Expression.new()
var parameters := PackedStringArray(["method_name", "args"])
var parse_err := expression.parse("callv(method_name, args)", parameters)
if parse_err != OK:
    push_error(expression.get_error_text())
else:
    var arguments := [method_name, method_arguments]
    var result = expression.execute(arguments, obj, true)
    if expression.has_execute_failed():
        push_error(expression.get_error_text())
    else:
        print(result)

```

Here we attempt to call `"my_method"` on the object `obj` with arguments `123` and `"abc"`.

This way you should get an error telling you if the method was not found or if there is any problem with the arguments.

Sadly, you have `has_execute_failed` returning a `bool`, and we lack an API to read which the error was other than `get_error_text` (which I guess you could parse).

However, this works similar to what you want: you call a method to know if there was a problem with the call.

---

## Checking with `is_valid` from `Callable`

I originally skipped callables, because I took the question as face value.

Yet, `Callable` has an `is_valid` method that looks promising. So, let us define a callable:

```
var my_callable := Callable(obj, "my_method")

```

And check if it is valid before calling:

```
var my_callable := Callable(obj, "my_method")
if my_callable.is_valid():
    my_callable.call()
else:
    push_error("invalid callable")

```

The problem is that this does not take into account the arguments. We might bind the arguments (this returns a new callable):

```
var my_callable := Callable(obj, "my_method")
my_callable = my_callable.bind(123, "abc")
if my_callable.is_valid():
    my_callable.call()
else:
    push_error("invalid callable")

```

But - upon testing - `is_valid` does not check if the bound arguments are valid. Thus, this `call` might still fail.
> 2 votes

---
Tags: c#, godot, gdscript, godot-4, code-reflection
---


# Question
Title: Unity's Camera.ScreenToWorldPoint is apparently "missing", what could be the cause?
I have a small Unity plugin project set up (working on fixing a broken mod), and the Camera class seems to be missing a method. I've added Unity dll assembly references, and everything is working except this ONE method. (I went by the advice of a tutorial which did this, so maybe there's a more correct way?)

It's about a 600 line file with lots of references to Unity stuff that are working fine, including other Camera references. In fact if I comment this bit out, the plugin builds and works fine.

This is what I'm importing:

```
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using UnityEngine;
using UnityEngine.Rendering;

```

When I inspect the Assembly (decompiled by Rider), this Camera.ScreenToWorldPoint method really is missing (see left view).

```
pos = mainCamera.ScreenToWorldPoint(new Vector3((float) ((double) mainCamera.pixelWidth * 0.5 - 50.0), (float) mainCamera.pixelHeight * 0.1f, 1f));

```

What else can I try or investigate to get to the bottom of this?

(I know this line of code looks like it does nothing, but I believe it actually IS doing something, because this is a Harmony "Prefix". It looks like it's modifying the value of the "pos" parameter passed into the method that Harmony is patching.)

# Answer
> 0 votes
My best guess is, that one of the other imports is providing as well a camera and you are using that one instead of the one from `UnityEngine`. What would support this is that there is no `ScreenPointToRay(Vector2 pos, Camera.MonoOrStereoscopicEye eye)` or `ScreenPointToRay_Injected(ref Vector2 pos, Camera.MonoOrStereoscopicEye eye)` in the documentation.

Check the namespace of the decompiled code and if you are using the wrong one, add the correct namespace to the Camera.

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


# Question
Title: Rotate UVs in shader and contains result into quad with repeat edge pixels
I ask for help - I need to rotate the UV scan inside the quad by a certain angle (set by a parameter) so that the result is embedded in the original UV, and the missing areas are repeat edge pixels. Example in the picture. Unity. How to do it? I can only simply rotate the scan, but not reduce it.

# Answer
Maybe someone will need it?

```
o.spriteCoord.xy = v.texcoord.xy;
o.spriteCoord.zw = float2(1, 1);

o.spriteCoord.x = (o.spriteCoord.x - 0.5) * _BoundsX + 0.5;
o.spriteCoord.y = (o.spriteCoord.y - 0.5) * _BoundsY + 0.5;

o.spriteCoord.xy = rotateUV(o.spriteCoord.xy, _Rotation);

o.spriteCoord.x = (o.spriteCoord.x - 0.5) / _ScaleX + 0.5;
o.spriteCoord.y = (o.spriteCoord.y - 0.5) / _ScaleY + 0.5;

```

Where bounds is the size in unit of the global width and height, and scale is the desired image scale
> 0 votes

---
Tags: unity, shaders, rotation, matrix
---


# Question
Title: Can I rotate the velocity of a rigid body?
In unity, I'm working on functionality for a shooting at the mouse position from the player's weapon in a top-down 2d game. I have a working gun that instantiates a bullet prefab, that moves towards the cursor as desired.

Now I want to add variation to the accuracy of the bullet. Ideally I want to get a random number, for example between -5 and 5, and "add" it to the rotation of the bullets velocity on Start(). I want to use a method like this so that the distance the mouse is from the player won't affect the accuracy of the shot.

Here's the code for the Bullet's Start()

```
void Start()
{
    mainCam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
    rigidBody = GetComponent<Rigidbody2D>();
    mousePos = mainCam.ScreenToWorldPoint(Input.mousePosition);
    Vector2 direction = mousePos - new Vector2(transform.position.x, transform.position.y);
    Vector2 rotation = new Vector2(transform.position.x, transform.position.y) - mousePos;

    rigidBody.velocity = new Vector2(direction.x, direction.y).normalized * force;
    float rot = Mathf.Atan2(rotation.y, rotation.x) * Mathf.Rad2Deg;
    transform.rotation = Quaternion.Euler(0, 0, rot + 90);
}

```

Is there someway to edit rigidBody.velocity to rotate the direction its set to move in? Or some way to get a similar affect?

The rotation bit is just to rotate the sprite to be inline with the direction, it doesn't affect the velocity.

# Answer
> 1 votes
I got it working using DMGregory's suggestion.

This line is the ticket, just adjust the "20".

```
rigidBody.velocity = Quaternion.Euler(0, 0, 20) * rigidBody.velocity;

```

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


# Question
Title: ForwardAdd pass gets weird results when a point light is on in Unity
I'm writing a custom shader for the transparent object with built-in pipeline of Unity2022.3.9f1.

For Subshader the Tags set like below

```
Tags { "LightMode"="ForwardBase" "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector" = "True"}

```

For base pass everything is ok and the Tags look like below

```
Tags { "LightMode"="ForwardBase"}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

```

And for additive pass, I set them like below

```
Tags { "LightMode"="ForwardAdd"}
Blend SrcAlpha One // Or Blend One One
ZWrite Off

```

Now when a point light is on, the blending is wrong no matter `Blend SrcAlpha One` or `Blend One One`. The result looks like below

I'm confused what happened and how should I fix this?

PS. I'm using Blinn Phong to illuminate everything and the code is

```
//Lighting
UNITY_LIGHT_ATTENUATION(atten, i, i.positionWS);

float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.positionWS));
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
float3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(normalWS, worldLightDir));
float3 halfDir = normalize(worldLightDir + viewDir);
float3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(normalWS, halfDir)), _Gloss);
float3 lighting = ambient + (diffuse + specular) * atten;

```

# Answer
> 0 votes
The funny thing is that I get rid of `ambient` in the ForwardAdd pass and then it's working as I imagine.

Quite confused...

---
Tags: unity, shaders, alpha-blending
---


# Question
Title: Is there a logical reason for SFML's Vector2 being templated?
The game development library SFML has a `Vector2` class template (and a `Vector3` for that matter), which can use any arithmetic type for its x- and y-value: `Vector2<float>`, `Vector2<int>`, `Vector2<double>`, etc.

My question is simply: Why? Why would you ever want to use any other type than `float` for positional math? I realize SFML is a public library that is made very open to suit what the user feels appropriate, but still. The library even has typedefs like `Vector2i` for `Vector2<int>`, and `Vector2u` for `Vector<unsigned int>`. What would any possible use-cases be for those two types?

I found this similar question and all answers say that float is pretty much always used. So what do you think is the idea behind SFML's `Vector2` being templated? Could it be merited?

# Answer
> 3 votes
Unity, for example, has both `Vector2` and `Vector2Int` types (and so on for other dimensionalities), since C# didn't/doesn't have good support for making math generic across different number formats. Peeking at their APIs can give a clue as to why game or engine developers might go to that trouble.

You'll find these types are used prominently in their grid and tilemap APIs for making **tile-based games**, where you naturally want positions to be expressed in units of discrete "hops", and fractions of tiles might not make sense. This gives you the familiar vector math tools for manipulating positions/displacements, footprints or selection bounds, while saving you unnecessary number format conversions when you want to use a tile position as an index into an array of tile types / contents. In particular, if the corner of your map is always (0,0) and tile positions are exclusively non-negative, then you can use unsigned types and be certain you'll never get an invalid negative index from them.

You might even opt to use a smaller integer type that's only 1 or 2 bytes, if your maps are never larger than 256 / 65536 tiles wide, or you can quantize your positions to that level of granularity for storage without negative gameplay impacts. That lets you pack more positions in a cache line for bulk operations, or to **compress** data packets for network communication in multiplayer, or to shrink the size of files you're loading/saving to disc.

It's also sometimes desirable when you want to store and manipulate cardinal direction vectors like (0, 1), and want to be certain that no matter what sequence of rotations/shifts you put them through, you'll never get **accumulating floating point rounding error** that makes them deviate from the expected values.

It's also sometimes the case that you need vectors to retain **high precision** even a **long distance from the origin**, where single-precision floating point numbers have to trade off significant precision for range. For instance, you can't make a scale representation of the solar system that both faithfully reproduces the orbits of planets AND lets you move around your spaceship on a scale of meters within a single 32-bit float coordinate system. When you hit this precision limitation, it can be convenient to work around it by adding more bits: trading up to 64-bit doubles, while keeping the rest of the code pretty much unchanged. (Though arguably a better solution for many such cases is to divide the space into chunks and express position relative to the nearest chunk origin instead — this will depend on the specifics of your application)

So that's four possible reasons why you might sometimes reach for a different number format in your vector types, even though 32-bit floats are "good enough" 90% of the time. If you're not making a game/tool that runs into one of those reasons, you can pretty safely ignore it and just use floats exclusively.

# Answer
> 2 votes
> Why would you ever want to use any other type than float for positional math?

The other answer covers this pretty well but some aspects of your post has not been tackled.

---

> Is there a logical reason for SFML's Vector2 being templated?

Because SFML is written in c++ and as such, you don't re-write code when you can template it instead. Failing to have done so would likely have let folks judge negatively the library.

> Why? \[...\] What would any possible use-cases be for those two types?

The answer lies partly here: "*\[...\] I realize SFML is a public library that is made very open to suit what the user feels appropriate \[...\]"*. SFML is built over other APIs, including Windows and OpenGL. The fact that floats are not used all over the place is likely due in part to *those* APIs, where they provide functions that accept ints and uints. Having SFML's own API use those can indicate to the end user something like "look, we'll pass ints anyway, so better handle what you want to do with decimal values rather than be surprised that we just ignore them or do something you wouldn't expect."

As an example, the Windows API CreateWindowW function used in Window class construction implementation uses `int`s for the positioning/size, and as such, `VideoMode` holds `Vector2u`.

---
Tags: c++, 2d, vector, sfml, floating-point
---


# Question
Title: Time aware point -> capsule swept collision detection?
the simplicity of Minkowski sums are one of the big reasons capsules are used in collision detection, especially for player models. One of the benefits of this *should* be the ability to perform collision detection *through time*, at least with simple primitives.

What I want to try is to collide a bullet (with some speed, represented by a point) and a capsule. A point bullet should *also* have a simple minkowski representation, and a bullet through *time* should just be a straight line, a point swept through time. Using this information, we should at least be able to derive the *time* of impact, which alone should allow for any other collision information we want. Basically similar to something like this: https://blog.hamaluik.ca/posts/swept-aabb-collision-using-minkowski-difference/

What I'm having trouble understanding however, is how to collide with a swept *capsule*, which itself is a swept *sphere*. I don't understand how I'm supposed to perform the collision, and I can't find any info online.

# Answer
> 0 votes
First, we'll do the check in the inertial frame of the bullet. We subtract the bullet's position and velocity from the capsule's position and velocity, and then sweep the capsule from its new relative position over its new relative velocity.

If this swept shape includes the origin, then the bullet hits the capsule. We can approximate that to a fair degree of accuracy by making two triangles out of the starting and ending positions of the centers of the top and bottom ends of the capsule, then doing two "distance from point to triangle" tests.

If the closest the shape gets to the origin is less than the capsule radius (plus the bullet radius, if it has one), then the bullet definitely misses. Otherwise you have a hit.

To find the time of the hit, we can take the shortest distance we got from our two triangle tests, and find the closest point to the origin on that triangle. That will correspond to a point on the center line segment of the capsule at a given moment. The barycentric coordinates of that point on the triangle tells you that time as a fraction of the time step. (The triangle either has two points in the present or one point in the future, or two in the future and one in the present — the barycentric coordinate corresponding to the odd point out is the fraction of the timestep you need to seek to from that point's time)

This time will usually be an over-estimate: the origin is already partly embedded inside the capsule at this moment. But you can compute the time since penetration by firing a ray backward from the origin along the relative velocity at that time & location, and finding where that ray exits the cylinder/spherical cap. That gives you a refined estimate for the moment the bullet first touched. For a capsule that is only translating/yawing, this will be exact. For a capsule that's pitching or yawing, you can test if this point is still inside the capsule at that time, and use binary search to reduce the error below your chosen threshold.

---
Tags: collision-detection, physics, projectile-physics
---


title: AI MoveTo always fails

text:
# Question
Title: AI MoveTo always fails
I try to move a character with AI MoveTo, but it always fails. I tried to do this with a standard ThirdPersonController and a custom one. The blueprint is simple

When the event happens, it starts printing "failed". I checked many times if I have a NavMesh on the level or any other problems with it, but I don't think there are any problems with that. Any ideas?

# Answer
> 1 votes
Long story short: there was some problem with the map, so I just started using another one. Don't know what caused the problem, but it was definitely in the map.

# Answer
> 1 votes
There's a few things that can cause this. Also, yes, it's normal to be frustrated with the AIMoveTo node, as it can be finicky. Your AIMoveTo node does not have a destination. Instead, try to drag off the `As First Person Character` and get the actor's world location. You should try inputting that into the `Destination` field on the AIMoveTo node.

If this doesn't help, make sure your AI pawn is possessed by AI (you can check this in the class (self) details under a field called `Auto Possess AI`.

One more thing, is the `OnSeePawn` event firing? It might be having issues seeing you.

I'm assuming the issue is the destination field, though. Keep me updated with this! I want to make sure you get this resolved.

# Answer
> 1 votes
I had the same problem with my project. Suddenly my AI stopped working.

By just selecting the **nav mesh volume** and changing anything(like a minor adjust in x scale, for example) made it work again.

Maybe Nav Mesh need some kind of refresh after some change in the project.

# Answer
> 1 votes
I had the same exact problem. I killed the `NavMesh`, deleted it, and deleted the `NavRecast`. The recast returned automatically, I made a new `NavMesh` and that did it.

# Answer
> 1 votes
Assuming that you've set everything up correctly and it's still failing; your Target Actor HAS to be in contact with the navmesh otherwise it will fail regardless of whether the move was successful or not.

I was having the same issue, and actually, what the problem was for me was that I was using a target point actor for the location my AI should move to, and it was in the air (247 units above the ground) and not touching the navmesh. So, it was arriving at the target, then getting confused and then failing after a few seconds, even though it was actually AT the target and the acceptance radius was 300. All I did was move the target point to the ground (pressed END with the target actor selected) and it immediately fixed the issue. So it will register as a fail if the move to target isn't connected to the navmesh even though it did technically walk to the target you specified.

# Answer
> 0 votes
One solution I found actually had to do with the `RunPhysicsWithNoController` boolean in the `CharacterMovementComponent`. I spawn my AI from the `gamemode` to populate servers that are below max player count, and I found that having that boolean as true keeps the character from moving.

# Answer
> 0 votes
I had the same issue for a few days and I just fixed it. If you're interested the issue was that RecastNavMesh had Runtime.CanBeMainNavData turned off by default, when I turned it on the AI started to move again. I hope this will help anyone.

# Answer
> 0 votes
No one actually says this but you actually **must** have a *navMeshBoundsVolume* in your scene that overlaps the Actor/Pawn AI so that it moves where you want it to move.

I had the same issue and fixed it by adding a **navMeshBoundsVolume** to my scene.

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


# Question
Title: Should networking and rendering be separated in multiple threads?
I've been trying to code a multiplayer client/server prototype game using SFML's networking. My server and client use TcpSelectors to wait for a certain amount of time for incoming packets without blocking the main thread; however, waiting for packets also means that the main thread won't render anything as long as the function hasn't returned yet. As a temporary solution, I've just made so the amount of time the TcpSelector waits for is 1/144th of a second; this way rendering will happen at a max of 144FPS. However, I think this is a very bad option: this effectively caps the game's rendering fps to 144, since trying to render any more than that won't be possible: just packet polling takes 1/144th of a second.

Because of this I had thought of moving my networking logic to another thread and then use a condition variable to signal whenever a packet has been received; my main problem however is that I have no idea how to make so my main thread doesn't wait indefinitely for a packet to arrive.

A solution would be to make my thread check the condition variable and then immediately keep rendering if no packet has been received.

How could I implement this? Is this even a good approach? Thank you.

# Answer
> 2 votes
Quick summary:

* You should be using non-blocking socket reads
* It's a reasonable but probably unnecessary optimization if your sockets are non-blocking
* You should probably be using UDP

Processing the network traffic in its own thread is a perfectly reasonable approach, but definitely not essential. Your instincts that you should not be blocking while waiting for network data are correct, but you can do that without multithreading.

First, as pointed out in a comment, you most likely do not want to be using TCP for your communication if this game is meant to take place in anything near real time. This does mean you need to account for some aspects that TCP handles for you, **but** you can do so in a way that is *far* more efficient than TCP's generalized implementation. You do also get one benefit from UDP that you have to account for manually with TCP, which is that when you read a packet it is always a complete message.

The standard way to account for the possible gaps in UDP is to give every update a sequential ID and include in the update an acknowledgement of the most recent update you have received from the other party. Each side then sends updates basically assuming that any updates that have been sent since the last acknowledged ID were lost. That may sound kind of wasteful, but in practice the amount of redundant data will tend to be very small and the time saved from negotiating re-sends will be huge.

Because every update includes all the data needed to match the most current state of the sender, lost updates don't have to be accounted for at all. If one does show up late and out of order, you will know this by the ID and just ignore it.

To be slightly more specific as to what this looks like on each side:

The Server: The simplest approach is to send the current state of all objects in the game. For a simple game, that could be all you need to do. The more efficient version is to send all of the values that have changed *since the last acknowledged update*. This means keeping a buffer of recent full updates on the server and generating a diff for the client update.

The Client: Send all input since the last acknowledged update. This can look like a couple of different things depending on your game. Common things are a queue of commands or timestamped changes in button state. The important thing is that inputs are re-sent until they are acknowledged.

If you do stick with TCP, you should set the sockets to be non-blocking so that recv() will return immediately if there is no data waiting. Also be sure to disable Nagle's Algorithm using the TCP\_NODELAY flag, otherwise you will likely experience significant lag.

Either way, what this looks like in a multithreaded setup is not much different than what it would look like to do it in a single thread. The network thread would continually attempt to recv() data and as soon as it does process it into whatever format the game expects. When a complete update is received and processed, it is put into a queue that is visible to the main thread. In the main thread, you will check that queue and process any waiting updates, rather than checking the socket directly. For absolute maximum efficiency, you would make it a lock-free queue.

While this will possibly by you some time, **in most cases this won't be a significant optimization.** The only way to know for sure is profile your game, but if you are already using the sockets in a non-blocking way, there is almost certainly something else to optimize that will be a *much* bigger win.

---
Tags: c++, networking, sfml, multithreading
---


# Question
Title: Change of computing power/ time needed when imported Mesh triangle number changes
I am doing a Unity project, that makes it necessary to import a mesh consisting of triangles. As it is possible to reduce the amount of triangles in a mesh and keeping the structure similar, I am wondering, what the theoretical expectation of the behaviour of the computational time and power would be. So for example, I am using a mesh with 100000 triangles vs. 50000 triangles. In the project a sphere will collide with the mesh at a certain point and time. What would be an approach to what to expect here? (From simply running the project, I did not notice a difference, but I would like to understand what happens "in the background"/ what I can expect for larger amounts of triangles.) Thank you very much in advance!

# Answer
> 0 votes
This depends on some specifics.

If the triangle mesh is using a convex collider, then only polygons on the convex hull contribute to the collision detection cost, while interior/co-planar triangles take time to import but are effectively ignored in collisions.

If the mesh is static, the physics engine may be able to sort it into an acceleration structure that lets it check only "nearby" triangles for collisions, rather than the full collection. So here it's the density of triangles per unit volume that matters, not necessarily the total number. (Though a larger number will still take more time and memory to import/load/distribute into the acceleration structure)

The best way to find out for your specific use case would be to take a simple mesh representative of what you'll be working with, then make a copy of it which you subdivide to some high degree. Make sure it stays curved or bumpy after subdivision, to deny Unity opportunities to auto-simplify some of the small triangles back to fewer, larger triangles in flat areas.

Import each mesh into an otherwise-identical scene where things will collide with them, and run the profiler to measure the exact time cost of the physics update in each case. Run several trials to control for flukes. Then crank up the subdivisions and try again. This will let you empirically plot the performance curve as it manifests for the collision scenarios you're using.

---
Tags: unity, collision-detection, performance
---