【Unity BehaviorDesigner】行为树插件自定义概率选择节点

文章描述了一位Unity新手如何修改BehaviorDesigner的RandomSelector脚本来实现根据自定义概率选择执行子节点,通过Fischer-Yatesshuffle算法生成随机选择。作者寻求优化方法和建议。
摘要由CSDN通过智能技术生成

前情提要

今天在用BehaviorDesigner插件时遇到了一个问题
我想要通过一个自定义的概率来执行子节点,但是由于本人对这个插件不是很了解,所以只知道插件自带有一个RandomSelector节点,这个节点是以相同的概率选择一个子节点执行,所以为了实现需求,我参照这个节点的脚本写了一个可以自定义每个子节点选择概率的脚本。

代码

using UnityEngine;
using System.Collections.Generic;
using System;

namespace BehaviorDesigner.Runtime.Tasks
{
    [TaskDescription("改写自RandomSelector脚本,将根据概率随机选择执行一次子节点")]
    [TaskIcon("{SkinColor}RandomSelectorIcon.png")]
    public class RandomSelectorByNums : Composite
    {
        [Tooltip("Seed the random number generator to make things easier to debug")]
        public int seed = 0;
        [Tooltip("Do we want to use the seed?")]
        public bool useSeed = false;

        [Tooltip("子节点概率队列,对应从左至右每个节点被选中的概率")]
        public List<int> Probabilities = new List<int>();

        // 每个子任务的索引列表。此列表由 Fischer-Yates shuffle 算法使用。
        private List<int> childIndexList = new List<int>();

        //最后一个子项的任务状态。
        private TaskStatus executionStatus = TaskStatus.Inactive;

        private int total;//总概率
        private int target;//本次执行所击中的子节点

        public override void OnAwake()
        {
            // If specified, use the seed provided.
            if (useSeed) {
                UnityEngine.Random.InitState(seed);
            }

            // Add the index of each child to a list to make the Fischer-Yates shuffle possible.
            childIndexList.Clear();
            for (int i = 0; i < children.Count; ++i) {
                childIndexList.Add(i);
            }

            if(Probabilities.Count<childIndexList.Count)
            {
                throw new Exception("概率列表数量少于子节点数量");
            }

            //将概率列表长度与子节点数量所匹配
            for (int i = Probabilities.Count - 1; i >= childIndexList.Count; i--)
            {
                Probabilities.RemoveAt(i);
            }


            //总概率
            foreach (var item in Probabilities)
            {
                total += item;
            }
            
        }

        public override void OnStart()
        {
                 
            target=GetTargetByRandom();
            //Debug.LogError("--------------------"+target);
        }

        private int GetTargetByRandom()
        {
            int thisHit = UnityEngine.Random.Range(0, total);
            int rangemin = 0;
            int rangemax = 0;
            for (int i = 0; i < childIndexList.Count; i++)
            {
                rangemin = rangemax;
                rangemax += Probabilities[i];
                if (thisHit >= rangemin && thisHit < rangemax)
                {
                    return i;
                }
            }
            return -1;//标记出错
        }

        public override int CurrentChildIndex()
        {
            // Peek will return the index at the top of the stack.
            //return childrenExecutionOrder.Peek();
            //return childIndexList[target];
            return target;
        }

        public override bool CanExecute()
        {
            // 是否能够继续执行&&该次目标是否执行完毕
            return !(executionStatus == TaskStatus.Success);

        }

        public override void OnChildExecuted(TaskStatus childStatus)
        {
            // 目标子节点执行后的状态
            
            executionStatus = childStatus;           
        }

        public override void OnConditionalAbort(int childIndex)
        {
            // 从终止状态开始
            executionStatus = TaskStatus.Inactive;
            target = GetTargetByRandom();
        }

        public override void OnEnd()
        {
            // All of the children have run. Reset the variables back to their starting values.
            executionStatus = TaskStatus.Inactive;
            //childrenExecutionOrder.Clear();
        }

        public override void OnReset()
        {
            // Reset the public properties back to their original values
            seed = 0;
            useSeed = false;
        }        
    }
}

使用

面板中选择使用
在这里插入图片描述
属性栏中有一个列表,这个列表存放着从左到右每个子节点的选择概率。
如1号子节点的选择概率对应Probabilities[0],也就是5/(列表每个数之和=5+5+5+5+80)
5号子节点的选中概率为80/100
本人是Unity新手,只能想到这种方法,如果有更好的办法欢迎大家告诉我!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值