[FreedomAI]第五周——AI的LOD

LOD——Level of Detail,多细节层次,这本身是图形学的一个概念,在图形学中,为了对性能进行加速,我们很正常的会有这样一个想法,对于那些比较远的图元,我们是不是可以不渲染他大量的细节,而只描绘出一个轮廓呢?——而这在视觉效果上其实并不会产生太大差距,因为往往比较远的图元真正体现在图元上仅仅只是几个像素而已。由此,在图形学中,我们往往会对图元设计多个细节层次,每个细节层次都表现出不同的细节程度,比如,第一级,启用阴影,光照模型,法线贴图,全部的Mesh,第二级,启用光照模型,法线贴图,全部Mesh,第三级,不用法线贴图................................

在AI中,其实我们发现,这个概念是可以类比的,玩家当然不会关心过于远的AI是在走在跑,是不是用一些策略有效的组织进攻。所以在AI中,我们同样引用了LOD的概念。

首先对所有的AI增加一个LODComponent的组件,存着AI的LOD级别,然后再用一个系统实时的计算LOD级别。

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

然后光有LOD的计算还是不够的,我们还有要切实的用出来。

在FSM中,我们本来是一秒中轮询一次节点是否发生转化,现在:

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

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

动画系统中:

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

在LOD非常高的时候,甚至直接取消了Animator。

在Emotion,FuSM等等系统中也存在着同样思路的优化。同时在逻辑节点中,也可以引用LOD参数,做一些用户级别想要的优化。


猜你喜欢

转载自blog.csdn.net/qq_33999892/article/details/80213125