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);
}
}
}
```