[FreedomAI] Week 5 - LOD of AI

LOD - Level of Detail, which is a concept in graphics itself. In graphics, in order to speed up performance, we normally have such an idea. For those primitives that are far away, we Wouldn't it be possible not to render him in a lot of detail, but to just draw an outline? ——And this does not actually cause much difference in visual effects, because often the distant primitives are only a few pixels in the primitives. Therefore, in graphics, we tend to design multiple levels of detail for primitives, and each level of detail shows a different level of detail, such as the first level, enabling shadows, lighting models, normal maps, all Mesh, level 2, lighting model enabled, normal map, Mesh all, level 3, no normal map.......................... ......

In AI, in fact, we found that this concept can be analogized. Of course, players will not care that the AI ​​that is too far is walking and running, and whether it uses some strategies to effectively organize attacks. So in AI, we also refer to the concept of LOD.

First, add a LODComponent to all AIs to store the LOD level of AI, and then use a system to calculate the LOD level in real time.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityECS;
using FreedomAI;

namespace FreedomAI
{
	public class LODComponent:UComponent
	{
		public int mLOD;
		public static int maxLOD;
	};

	public class LODUpdateSystem:USystem
	{
		public static float[] lodDistance;

		public static GameObject mPlayer;

		public override void Init ()
		{
			base.Init ();
			this.AddRequestComponent (typeof(LODComponent));
		}

		public override void Update (UEntity uEntity)
		{
			base.Update (uEntity);
			if (lodDistance.Length == 0)
				return;
			if (mPlayer == null)
				return;
			GameObject tObject = getObjectByEntity (uEntity);
			float dis = Vector3.Distance (mPlayer.transform.position,tObject.transform.position);
			for (int i = 0; i < lodDistance.Length; i++)
			{
				if (dis < lodDistance [i])
				{
					uEntity.GetComponent<LODComponent> ().mLOD = i + 1;
					return;
				}
			}
			uEntity.GetComponent<LODComponent> ().mLOD = lodDistance.Length + 1;
		}

		private GameObject getObjectByEntity(UEntity uEntity)
		{
			if (uEntity.GetComponent<BaseAIComponent>()!=null);
				return uEntity.GetComponent<BaseAIComponent> ().mAIRT;
			else
				return ((SimpleAI)uEntity).mAIRT;
		}

	}

};

public class AILOD:MonoBehaviour
{
	public float[] LODDistance;
	void Start()
	{
		LODUpdateSystem.lodDistance = LODDistance;
		LODComponent.maxLOD = LODDistance.Length+1;
		LODUpdateSystem.mPlayer = GameObject.FindGameObjectWithTag ("Player");
	}
}

Then the calculation of LOD alone is not enough, we still have to use it practically.

In FSM, we used to poll the node once a second for conversion, now:

			int lod = uEntity.GetComponent<LODComponent>().mLOD;

			if (uEntity.GetComponent<AIState> ().timer <= 1.0f*lod)
			{
				uEntity.GetComponent<AIState>().timer += Time.deltaTime;
				return;
			}

In the animation system:

public override void Update (UEntity uEntity)
		{
			int lod = uEntity.GetComponent<LODComponent>().mLOD;
			Animator tAnimator = uEntity.GetComponent<AIAnimation>().mAnimator;

			if (lod > (LODComponent.maxLOD) / 3 * 2)
				tAnimator.enabled = false;
			else
				tAnimator.enabled = true;

			if (lod > (LODComponent.maxLOD)/2)
				return;

			AnimationPlay tAnim = uEntity.GetComponent<AIAnimation>().Get(uEntity.GetComponent<AIAnimation>().tempAnim);

			tAnim(tAnimator);
		}

When the LOD is very high, the Animator is even canceled directly.

There are also optimizations of the same idea in Emotion, FuSM and other systems. At the same time, in the logical node, you can also refer to the LOD parameter to do some optimizations that the user wants.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325767255&siteId=291194637