Farseer Assertion Failure - c#

We're creating a game for a school project. It's a 2D platformer and it is in its very early stages. We use C#/XNA and we're implementing Farseer Physics Engine.
I'm currently struggling with the map-class. In the class we have a List of DrawableGameObjects, were we store each tile of the map and draw them. But when we try to draw them we get a "Assertion Failed". Examining the problem even further I've come to the conclusion that whenever we try to add more than to static bodies to the world (even without drawing them) we get this failure. Throw message
Game1.cs:line 210 is:
world.Step(0.033333f);
And Program.cs:line 15 is:
game.Run();
Here is the code for the Map class:
class Map
{
private List<DrawableGameObject> ground = new List<DrawableGameObject>();
public Map(World world, Texture2D texture)
{
for (int i = 0; i < 32; i++)
{
DrawableGameObject floor = new DrawableGameObject(world, texture, new Vector2(40, 40), 100, "ground");
floor.Position = new Vector2(i * 40, 500);
floor.body.BodyType = BodyType.Static;
ground.Add(floor);
}
}
public void Draw(SpriteBatch spriteBatch){
foreach (DrawableGameObject dgo in ground)
dgo.Draw(spriteBatch);
}
}
Any ideas? I've posted the problem on Farseer's forum, but they haven't been very helpful yet...

This is a bug in Farseer. (Version 3.3.1)
I opened up the Farseer source code to the method in question (World.SolveTOI) and found two calls to Debug.Assert. And, in fact, in my copy of the code, I've actually already come across this bug and commented one of them out, specifically:
Debug.Assert(typeA == BodyType.Dynamic || typeB == BodyType.Dynamic);
Basically it doesn't want to attempt to handle contacts between two bodies that are static.
Fortunately the code immediately below actually checks for essentially the same condition, and continues the loop if that is the case:
bool awakeA = bA.Awake && typeA != BodyType.Static;
bool awakeB = bB.Awake && typeB != BodyType.Static;
// Is at least one body awake?
if (awakeA == false && awakeB == false)
{
continue;
}
So it's quite safe to simply comment out or remove the assertion. (You should, of course, be building Farseer from source - it makes life much easier.)
To reproduce the Farseer bug: Have two static bodies and one dynamic body that is in contact with both, then make the dynamic body static. The assert will trigger.
The assert is in the contact handling loop. Normally a pair of static bodies wouldn't create contacts. But if a body starts out as dynamic, contacts can be created - they don't get removed when the body is made static.

Related

Unity Script only works with long namespace name

I tried following this Unity ECS Entity Manager Tutorial from Turbo Makes Games.
I'm using Unity 2020.3.20f1.1086.
The Code works initially but I noticed, that Line 20 in SpawnEntitiesSystem.cs EntityManager.SetComponentData(newEntity, newPosition); stops working when I change or remove the namespace. After tinkering a bit with the code I can reproduce that the specific namespace is not important but the namespace has to be at least 18 characters long for the code to work as expected. If I change the namespace to 17 characters all entities are spawned at the same place. Other code after the faulty line 20 was executed but for readability I removed it from the code example. (Originally user input was also handled and in OnStartRunning a component was added to the new entitiy)
I only heard of similar problems in e.g. C++ when using pointer maths but I thought something like this shouldn't happen in C#. Does anyone have an idea what the core problem could be?
What I already tried without succes
restart Unity
delete Library, Obj and Logs folders
write code from scratch in new project
restart PC
SpawnEntitiesSystem.cs
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace ALongNamespaceABCD {
public class SpawnEntitiesSystem : SystemBase {
private int2 _entitySpacing;
protected override void OnStartRunning() {
var entitySpawnData = GetSingleton<EntitySpawnData>();
var gridSize = entitySpawnData.SpawnGrid;
_entitySpacing = entitySpawnData.EntitySpacing;
for (int x = 0; x < gridSize.x; x++) {
for (int y = 0; y < gridSize.y; y++) {
var newEntity = EntityManager.Instantiate(entitySpawnData.EntityPrefab);
var newPosition = new LocalToWorld { Value = CalculateTransform(x, y) };
EntityManager.SetComponentData(newEntity, newPosition);
}
}
}
private float4x4 CalculateTransform(int x, int y) {
return float4x4.Translate(new float3 {
x = x * _entitySpacing.x,
y = 1f,
z = y * _entitySpacing.y
});
}
protected override void OnUpdate() {}
}
}
EntitySpawnData
using Unity.Entities;
using Unity.Mathematics;
[GenerateAuthoringComponent]
public struct EntitySpawnData : IComponentData {
public Entity EntityPrefab;
public int2 SpawnGrid;
public int2 EntitySpacing;
}
Edit:
I tried around a bit more and found out that it seems that the correct position will be set correctly at first. But it will instantly be overwritten by the prefabs Transform component. So maybe it has to do with converting the Prefab to an entity (I use the default Convert to Entity component) or a problem with some internal multithreading occurs.
Well, we finally got a response from Unity. Here is what they said:
This is intended behavior and will therefore be set to "won't fix".
The reasons are this:
Changing the name (and namespace) of a system changes its default position in the frame, this is expected behavior.
The SpawnEntitiesSystem from the provided repro project is not using any explicit system ordering attribute like
UpdateAfter/UpdateBefore/UpdateInGroup, so it follows the default.
Because it is expected behavior but nonetheless surprising, we have a task in the backlog about making the default order not depend on the
name in the future.
The prefab being instantiated has a Translation component and a Rotation component in addition to the LocalToWorld component.
The transform system from entities updates LocalToWorld based on the values of Translation and Rotation.
A direct modification of LocalToWorld conflicts with the transform system, and that modification will be overwritten.
Because Translation and Rotation are still at their default values, the expected outcome is that the transform system will compute an
identity LocalToWorld and put the instances back to the origin.
Unfortunately there is a bug in that particular setup (where the system doing the modification does it in OnStartRunning and executes
immediately after the transform system, if the namespace is long
enough to put it after the transform system) that causes the newly
spawned instances to never be noticed by the transform system. And it
is because of that bug that the cubes would show in the intended grid
layout by accident.
Source: https://issuetracker.unity3d.com/issues/entity-localtoworld-position-is-overwritten-by-prefab-position-when-namespace-is-17-characters-long-or-shorter
So, apparently, this whole situation happens because the LocalToWorld is sometimes being overwritten due to operation ordering that the length of the namespace is able to change. But this won't be the case in a future version.
A workaround is to set the Translation instead of the LocalToWorld Data.
Working code:
EntityManager.SetComponentData(newEntity, new Translation {
Value = new float3(
10.0f,
1.0f,
10.0f
)
});

Unity - Instantiated objects spawn on the same position in Coroutine, while instantiate them directly do spawn correctly

What i want to achieve:
Im creating a procedural generated city. I got the roads working, together with the spawning of the houses, they spawn along the road and dont get spawned if they are colliding with either the road and/or another building. Now since i sometimes i want to load a big city, this costs a lot of computing time, so i wanted to put in a Coroutine to slowly load in all the houses. (Please tell me if there is a better way, or a "correct" way, this is the only thing that i knew that could work).
What i did / Problem:
So what i did, is all the segments i use to create a house i put in a list, and once all the houses are pregenerated (not spawned/instantiated yet) i want to use the coroutine to spawn them individually. But whenever i use the coroutine to spawn them, they spawn inside eachother.
While if i spawn them directly from their script (still using the list) they do spawn correctly, i have no clue what i am doing wrong and how to fix this.
public void Spawner(Vector3 buildingPosition, Quaternion buildingRotation, int buildingHeight, GameObject buildingParent, LayerMask m_LayerMask, BuildingGenerator buildGenerator)
{
GameObject baseBuilding = buildingBase[Random.Range(0, buildingBase.Count)];
baseBuilding.transform.position = buildingPosition;
baseBuilding.transform.rotation = buildingRotation;
Debug.Log(baseBuilding.transform.position);
Collider[] hitColliders = Physics.OverlapBox(baseBuilding.transform.position, baseBuilding.GetComponentInChildren<Renderer>().bounds.extents /2, Quaternion.identity, m_LayerMask);
if (hitColliders.Count() > 1)
{
return;
}
buildGenerator.Segments.Add(baseBuilding);
buildingPosition.y += baseBuilding.GetComponentInChildren<Renderer>().bounds.max.y - buildingPosition.y;
for (int i = 0; i <= buildingHeight; i++)
{
buildingRotation *= Quaternion.Euler(0, 0, 0);
GameObject middleBuilding = buildingMiddle[Random.Range(0, buildingMiddle.Count)];
middleBuilding.transform.position = buildingPosition;
middleBuilding.transform.rotation = buildingRotation;
//buildGenerator.Segments.Add(middleBuilding);
buildingPosition.y += middleBuilding.GetComponentInChildren<Renderer>().bounds.max.y - buildingPosition.y;
}
if (buildingRoof.Count != 0)
{
GameObject roofBuilding = buildingRoof[Random.Range(0, buildingRoof.Count)];
roofBuilding.transform.position = buildingPosition;
roofBuilding.transform.rotation = buildingRotation;
buildGenerator.Segments.Add(roofBuilding);
}
Instantiate(buildGenerator.Segments[1]); //If i use this, they spawn on the correct place.
Debug.Log(buildGenerator.Segments.Count);
}
{
StartCoroutine(LoadSegments(buildingParent));
}
public IEnumerator LoadSegments(GameObject buildingParent)
{
for (int i = 0; i < Segments.Count; i++)
{
GameObject SpawnedSegment = Instantiate(Segments[i]);
//SpawnedSegment.transform.parent = buildingParent.transform;
yield return new WaitForEndOfFrame();
}
}
Extra info:
I make use of 3 scripts to spawn the whole city, the roadGenerator, which will spawn the roads, those road points get stored in a list. After the roads are generater the roadgenerator will call the building Generator. The building generator will go through the whole list of all the roads, and create buildings aside them, the buildings are created via a 3rd script (not instantiated). The building script, this script contains the building segments, and will piece them together and also check for collisions (First code block). Once these buildings are all created and put into a list, the buildingGenerator will start the coroutine and instantiate all these buildings (thus on the wrong position)(Second code block).
Hope i provided enough information, else id be happy to provide more.
Okay so i finally got it working. The problem was not at the coroutine, but at the list. My code would constantly override my list objects. So i created a new script, with basic attributes like the object, the position and rotation. So then i add those new scripts to the list, and spawn them in the coroutine. (In my comment i said i had some other problems after i fixed this, this is because i used .bounds.max.y, while i should have used .bounds.size.y. This is thus also the fix for that).
I hope someone in the future might find this helpful!

Game loop collision detection performance

I'm working on a Windows 10 2D board game, that sometimes can generate a chain reaction, where 144 moving objects can collide with 36 non-moving objects. This is the "worst" possible situation.
Every moving game object is created by some non-moving game object. The non-moving game object "shoots" moving game objects, and something happens when they collide with other non-moving game object :)
I'm using storyboards for moving XAML objects (UserControls), and checking for collisions with game loop based on CompositionTarget.Rendering.
Everything works great at my PC, but problem occures when I'm trying to make this effect on phone.
My game loop looks like this:
foreach (var movingGameObject in GameCanvas.Children.OfType<MovingGameObect>())
{
if (movingGameObject.Visibility == Visibility.Visible)
CheckCollision(movingGameObject);
}
CheckCollision method looks like this:
var left = Canvas.GetLeft(movingGameObject);
var top = Canvas.GetTop(movingGameObject);
var right = left + movingGameObject.Width;
var bottom = top + movingGameObject.Height;
// If left Canvas - remove
if (left <= 0 || right >= GameCanvas.ActualWidth || top <= 0 || bottom >= GameCanvas.ActualHeight)
{
RemoveMovingGameObject(movingGameObject);
return;
}
else
{
// Since it can go 4 ways - I check if it moves up, down, right or left
if (movingGameObject.Way == Way.Left)
{
for (/* this is being done max 5 times, I checked it. It gets every possible game object id that may be on the way of moving game object */)
{
if (this._gameObjects[i].IntersectsWith(movingGameObject))
{
RemoveMovingGameObject(movingGameObject);
GameObjectHit(this._gameObjects[i], null);
return;
}
}
}
else if (movingGameObject.Way == Way.Right)
{
//SAME HERE
}
// SAME FOR UP and DOWN
}
The GameObjectHit method checks if non-moving game object has to shoot another moving game objects etc. So when this is very bad scenario, game loop iteration has to check for collision and sometimes produce another moving object(s) and shoot it(them).
And IntersectsWith method:
var x1 = Canvas.GetLeft(this);
var y1 = Canvas.GetTop(this);
var r1 = new Rect(x1, y1, this.ActualWidth, this.ActualHeight);
var x2 = Canvas.GetLeft(mgo2);
var y2 = Canvas.GetTop(mgo2);
var r2 = new Rect(x2, y2, mgo2.ActualWidth, mgo2.ActualHeight);
r1.Intersect(r2);
if (!r1.IsEmpty)
return true;
else
return false;`
Oh, almost forgot. What's happening on phone? Game loop is being called not enough times and it don't check for collisions fast enough (moving objects just fly through non-moving objects).
I tried everything I possibly can to tweek a performance. I know that Windows 10 Mobile is in beta version and it will be faster, but the gameloop is being called ~2 times a second when it gets hot, so that's not the system fault.
For anybody struggling with this problem in the future:
YES - this was a XAML-based performance issue.
I re-wrote the code with MonoGame (XNA) and there is no problem. Everything works just fine even on low-budget Nokia Lumia 635:)
I did not try Win2D option, but suspect the result would be as good as it is with MonoGame.
Thanks everybody for replies.

Custom List .Remove

Heyo. First of all, I'm sorry if I'm asking something that's really simple. It's been holding me up for a day or two and I can't find any tutorials that cover what it is I'm trying to do.
I have a set of cubes that have to hold some game objects, along with an int that displays how important that object is and where it will appear in something called the Resolution Order. That bit is all working fine.
The CubeContents class:
public class CubeContents : IComparable<CubeContents>{
public GameObject objectType;
public int resolutionOrder;
public CubeContents (GameObject name, int importance){
objectType = name;
resolutionOrder = importance;
}
public int CompareTo(CubeContents other){
if(other == null)
return 1;
return resolutionOrder - other.resolutionOrder;
}
The method I'm using passes the specific game object to cube and uses this code to add it to the array:
public void newArrival(GameObject incoming){
int importance = discoverImportanceOfObject (incoming);
thisContents.Add (new CubeContents (incoming, importance));
thisContents.Sort ();
}
discoverImportanceOfObject is basically a long list of "else if" statements that returns a number I'm using to order these things. The problem I'm having is when I'm trying to remove this object from the array before I destroy it. This piece of code basically seems totally non responsive, but it compiles and runs just fine. No odd error messages, nothing.
public void leavingObject(GameObject leaving){
int importance = discoverImportanceOfObject (leaving);
thisContents.Remove (new CubeContents (leaving, importance)));
thisContents.TrimExcess ();
}
I'm at a total loss as to why this is. I've tried all sorts of things (IndexOf, then a RemoveAt, nulling out the entire array and then rebuilding it based on colliders...)
This just feels like it'll be a simple fix that I'm completely overlooking, but as I don't have an error message to search, or any other sort of jumping off point, I'm a bit stuck...
This object will not exist...
thisContents.Remove (new CubeContents (leaving, importance)));
Instead, loop through the thisContents collection to find the object matching the 'leaving' and 'importance'. Then remove that object.

How to find inactive objects using GameObject.Find(" ") in Unity3D?

I needed to find inactive objects in Unity3D using C#.
I have 64 objects, and whenever I click a button then it activates / inactivates objects for the corresponding button at runtime. How can I find inactive objects at this time?
Since Unity 2020
In the years since this question was asked, Unity put in the exact thing you need. At least, the exact thing I needed. Posting here for future peoples.
To find an object of a certain type whether it's on an active or inactive GameObject, you can use FindObjectsOfType<T>(true)
Objects attached to inactive GameObjects are only included if inactiveObjects is set to true.
Therefore, just use it like you regularly would, but also pass in true.
The following code requires System.Linq:
SpriteRenderer[] onlyActive = GameObject.FindObjectsOfType<SpriteRenderer>();
SpriteRenderer[] activeAndInactive = GameObject.FindObjectsOfType<SpriteRenderer>(true);
// requires "using System.Linq;"
SpriteRenderer[] onlyInactive = GameObject.FindObjectsOfType<SpriteRenderer>(true).Where(sr => !sr.gameObject.activeInHierarchy).ToArray();
The first array includes only SpriteRenderers on active GameObjects, the second includes both those on active and inactive GameObjects, and the third uses System.Linq to only include those on inactive GameObjects.
See this answers for Unity 2020 and higher.
Before Unity 2020
Well, using GameObject.Find(...) will never return any inactive objects. As the documentation states:
This function only returns active gameobjects.
Even if you could, you'd want to keep these costly calls to a minimum.
There are "tricks" to finding inactive GameObjects, such as using a Resources.FindObjectsOfTypeAll(Type type) call (though that should be used with extreme caution).
But your best bet is writing your own management code. This can be a simple class holding a list of objects that you might want to find and use at some point. You can put your object into it on first load. Or perhaps add/remove them on becoming active or inactive. Whatever your particular scenario needs.
If you have parent object (just empty object that plays role of a folder) you can find active and inactive objects like this:
this.playButton = MainMenuItems.transform.Find("PlayButton").gameObject;
MainMenuItems - is your parent object.
Please note that Find() is slow method, so consider using references to objects or organize Dictionary collections with gameobjects you need access very often
Good luck!
For newer Unity versions this answer provides probably a better solution!
First of all
In general any usage of Find or it's variants should be avoided.
Actually they are never really required but only a "hot-fix" used to cover an implementation "laziness".
Usually from the beginning storing and passing on required references is always the better approach.
Especially in your case you seem to have a fix amount of objects so you could probably already reference them all in a certain "manager" component and store them in a list or array (them you can get a reference by index) or even a Dictionary<string, GameObject> (then you can also get the according reference by name - you can find an example below).
Workarounds
There are alternative solutions (FindObjectsWithTag, FindObjectsOfType) but it will always be quite expensive (though most of the Find variants are expensive anyway).
You could e.g. also "manually" iterate through all objects in the scene using Scene.GetRootGameObjects
Returns all the root game objects in the Scene.
And then search through them until you find your object. This way you get also inactive GameObject.
public static GameObject Find(string search)
{
var scene = SceneManager.GetActiveScene();
var sceneRoots = scene.GetRootGameObjects();
GameObject result = null;
foreach(var root in sceneRoots)
{
if(root.name.Equals(search)) return root;
result = FindRecursive(root, search);
if(result) break;
}
return result;
}
private static GameObject FindRecursive(GameObject obj, string search)
{
GameObject result = null;
foreach(Transform child in obj.transform)
{
if(child.name.Equals(search)) return child.gameObject;
result = FindRecursive (child.gameObject, search);
if(result) break;
}
return result;
}
But ofcourse this should be strongly avoided and the usage of such deep searches reduced to a minimum!
What I would do
Another way - in my eyes the best approach here - could be to have a certain component attached to all your objects and actually store all the references once as said before in a dictionary like e.g.
public class FindAble : MonoBehaviour
{
private static readonly Dictionary<string, GameObject> _findAbles = new Dictionary<string, GameObject>();
public static GameObject Find(string search)
{
if(!_findAbles.ContainsKey(search)) return null;
return _findAbles[search];
}
private IEnumerator Start()
{
// Wait one frame
// This makes it possible to spawn this object and
// assign it a different name before it registers
// itself in the dictionary
yield return null;
if(_findAbles.ContainsKey(name))
{
Debug.LogError($"Another object with name /"{name}/" is already registered!", this);
yield break;
}
_findAbles.Add(name, gameObject);
}
private void OnDestroy ()
{
if(_findAbles.ContainsKey(name))
{
_findAbles.Remove(name);
}
// Optionally clean up and remove entries that are invalid
_findAbles = _findAbles.Where(kvp => kvp.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
}
and then use it like
var obj = FindAble.Find("SomeName");
if(obj)
{
// ...
}
Also for this the component would need to be enabled at least once so Start is called.
Again an alternative would be to have instead a
public void Initialize(string newName)
{
if(_findAbles.ContainsKey(name))
{
Debug.LogError($"Another object with name /"{name}/" is already registered!", this);
return;
}
name = newName;
_findAbles.Add(name, gameObject);
}
which you could call also after e.g. spawning an inactive object.
You can use Predicates.
Just get the gameObjects and check them whith a Predicate as below:
public List<GameObject> FindInactiveGameObjects()
{
GameObject[] all = GameObject.FindObjectsOfType<GameObject> ();//Get all of them in the scene
List<GameObject> objs = new List<GameObject> ();
foreach(GameObject obj in all) //Create a list
{
objs.Add(obj);
}
Predicate inactiveFinder = new Predicate((GameObject go) => {return !go.activeInHierarchy;});//Create the Finder
List<GameObject> results = objs.FindAll (inactiveFinder);//And find inactive ones
return results;
}
and don't forget using System; using System.Collections.Generic;
You can do this at runtime by having your inactive gameobject under an active parent object as previously mentioned; slightly different from what was mentioned, this is an approach I've used for activating/deactivating menus that should be inactive by default:
canvas = GameObject.FindGameObjectWithTag("GameMenu").GetComponentInChildren<Canvas>().gameObject;
Now you can change its activeSelf to toggle it in a method/event listener of your choice:
canvas.SetActive(!canvas.activeSelf);
Even while it is inactive, you can still use the tag property of it and use it for a filter, if getting multiple components of the same type. I haven't tested this using GetComponentsInChildren, but you could probably use a 'Single' linq query, and get the object by tag name which would require creating a tag for every gameobject you want to do this to.
Although its not the correct answer, but this is what I did in my case.
1) Attach a script to (inactive) game objects and instead of setting then inactive keep it active.
2) Position them out of the scene somewhere.
3) Set a flag in the script which says inactive.
4) In Update() check for this inactive flag and skip function calls if false.
5) When needed the object, position it at the proper place and set the flag active.
It will be a bit of a performance issue but that's the only workaround I could think of so far.

Categories