Finding Asset in Scene

I’m trying to find a model in a scene created in the editor. But I can not get a lock on the asset which happens to be the terrain model so I can get the width and height of it in a vector 2 to set camera bounds. Can anyone shine some light on how to find the asset directly by name in the scene?

First a precision: the concept of assets only exist at design-time. At runtime you have contents.

A scene (or a prefab) contains essentially entities. Your terrain model will be assigned to a model component on one entity in your scene. What you need to do then is to find your entity and get its component.

To find a entity by name, you can for example start from the root entities and iterate through the scene tree:

var scene = Entity.Scene;
var myTerrain = scene.RootEntities.DepthFirst(x => x.GetChildren()).FirstOrDefault(x => string.Equals(x.Name, "MyTerrain"));
var modelComp = myTerrain?.Get<ModelComponent>();
var model = modelComp?.Model;

I did not detail the DepthFirst() utility method. Basically it is like its name implies and depth-first iteration of the tree using the GetChildren() extension method to get the children entities of a given entity. You can implement a breadth-first search if you prefer, it doesn’t really matter.

Of course this is highly inefficient. A better way would be to have a script with an Entity or ModelComponent property that you could assign from the scene editor in the GameStudio. Even if your model is say generated at runtime, you can already place an empty entity in the scene at design time and reference it in a script.

Thank you I’m going to try this and see what I come up with.

What version of Xenko are you using because I’m on the newest 2.0 and I don’t see “scene.RootEntities” but I do have “scene.Entities”. I also don’t have “.DepthFirst” even after adding the “System.Linq”. Do you have modification outside of the normal Xenko & Linq library?

So this is what I came up with for finding the terrain.

        var TerrainAsset = Entity.Scene.Entities.FirstOrDefault(x => string.Equals(x.Name, "785"));
        var TerrainComponent = TerrainAsset?.Get<ModelComponent>();
        var TerrainModel = TerrainComponent?.Model;
        _TerrainBoundingBox = TerrainModel.BoundingBox.GetCorners();

Also how are you pasting code into the WYSIWYG editor?

What version of Xenko are you using because I’m on the newest 2.0 and I don’t see “scene.RootEntities” but I do have “scene.Entities”.

Ah yes sorry. It is indeed just called Entities in the Scene class.

I also don’t have “.DepthFirst” even after adding the “System.Linq”.

You will have to write DepthFirst() or BreadthFirst() yourself. You can find different implementation online. Here is one for example for BreadthFirst():

public static IEnumerable<T> BreadthFirst<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector)
{
    if (childrenSelector == null) throw new ArgumentNullException(nameof(childrenSelector));

    var queue = new Queue<IEnumerable<T>>();
    queue.Enqueue(source);

    while (queue.Count > 0)
    {
        var current = queue.Dequeue();
        if (current == null)
            continue;

        foreach (var item in current)
        {
            yield return item;
            queue.Enqueue(childrenSelector(item));
        }
    }
}

Also how are you pasting code into the WYSIWYG editor?

Huh. CTRL+C / CTRL+V

Sorry i thought the WYSIWYG editor had like a special way to insert the HTML tags for or

.

Thank you for responding I will research this more i did a quick search on it to start with but came up with no insight on the DepthFirst() call. Probably make it a extension class.

So glad you figured this out! I’m using this so my enemy that is spawned can find the player.