CocosCreator3.7.4 red dot system

Make explosive changes according to Unity’s red dot system

import { _decorator, Component, Node } from 'cc';

export class RedPoint
{
    //path
    path:string = "";

    //name
    name:string = "";

    //Superior relationship
    parent:RedPoint[] = [];

    //Subordinate relationship
    child:RedPoint[] = [];

    //Whether it is lit
    IsLit:boolean = false;
 
    //structure
    constructor(_name:string,_parent?:RedPoint)
    {
        this.name = _name;

       this.path =_name;

        if(_parent != null & amp; & amp; _parent != undefined )
        {
            this.parent.push(_parent);
            _parent.GetChilds().push(this);
        };
    }

   //Get the parent Root/1/a The parent of a is Root/1 Root
    GetParents():RedPoint[]
    {
       return this.parent == null?null:this.parent;
    }

//Get the parent, which is the last digit in the parent array Root/1/a Root/1
    GetParent():RedPoint
    {
        if( this.parent[ this.parent.length - 1] == null)
        {
            return null;
        }
        return this.parent[this.parent.length - 1];
    }
//Get child node end node child[] length==0
    GetChilds():RedPoint[]
    {
       return this.child == null?null:this.child;
    }
//Is this the last node?
    GetLastNode():boolean
    {
       return this.child.length == 0?true:false;
    }
//Get the status whether it is on or not
    GetState():boolean
    {
        return this.IsLit;
    }
//Only the last node can modify the value directly
//The nodes at the middle root calculate whether they should be lit based on their own child nodes.
    public ChangeState(state:boolean):void
    {
        //If it is the last node
       if(this.GetChilds().length == 0)
       {
          this.ChangeState_Last(state);
       }
    }

    //The last node can be changed directly
    public ChangeState_Last(state:boolean)
    {
        this.IsLit = state;

        //The reverse cycle of luxury animals can be executed from the next level up.
        for(let i = this.GetParents().length - 1; i >= 0; i--)
        {
            this.GetParents()[i].ChangeState_NotLast();
        }
    }

    //If it is not the last node, it must traverse the child nodes to dynamically change the value.
    public ChangeState_NotLast()
    {
        if(this.child.length == 0)
        {
            throw new Error("Not the last node");
        }

        this.IsLit = false;

        this.child.forEach(child => {
            //If the child node has a lighted parent node, it will light up.
            if(child.GetState() == true)
            {
               this.IsLit = true;
               return;
            }
            
        });

       // console.info(this);
    }


}



The basic red dot class is the red dot manager.

import { _decorator, Component, Node } from 'cc';
import { RedPoint } from './RedPoint';

/**
 * Tree structure is not a grammatical structure
 */
export const Root:string = "Root";
export const Root_LevelUp:string = "Root/LevelUp";
export const Root_LevelUp_BianXianLi:string = "Root/LevelUp/BianXianLi";
export const Root_LevelUp_BiaoYanLi:string = "Root/LevelUp/BiaoYanLi";
export const Root_LevelUp_YingXiangLi:string = "Root/LevelUp/YingXiangLi";
export const Root_Task:string = "Root/Task";
/**
 * The writing method of the original Unity is similar to Cpp. If the registered check delegation is legal, it will be added. If it is illegal, it will be deleted. Dynamically delete and add. The strings are also cropped and optimized.
 * In this version, nodes will always exist. A complete tree will always be in memory, but it will save performance in operation.
 * The status of child nodes is only true and false
 * The original refresh method adopts the UGUI refresh method.
 */
export class RedPointManager extends Component {

    public static Instance: RedPointManager = null as unknown as RedPointManager;
 
    onLoad(): void {
      if (RedPointManager.Instance === null) {
        RedPointManager.Instance = this;
      // this.InitData();
      }
      else {
        this.destroy();
        return;
      }
    }

    m_AllNodes:Map<string,RedPoint>;
    
    m_allLastNodes:RedPoint[] =[];

    SplitChar:string = "/";

    Root:RedPoint;

    InitData():void
    {
       this.m_AllNodes = new Map<string,RedPoint>();
       this.m_allLastNodes = [];
       this.SplitChar= "/";
       this.Root = new RedPoint(Root);
       this.InitNodeTree();
    }

    //Build tree
    InitNodeTree()
    {
      this.m_AllNodes.set(Root,this.Root);
      this.m_AllNodes.set(Root_LevelUp,new RedPoint(Root_LevelUp,this.Root));
      this.m_AllNodes.set(Root_LevelUp_BiaoYanLi,new RedPoint(Root_LevelUp_BiaoYanLi,this.GetNode(Root_LevelUp)));
      this.m_AllNodes.set(Root_LevelUp_BianXianLi,new RedPoint(Root_LevelUp_BianXianLi,this.GetNode(Root_LevelUp)));
      this.m_AllNodes.set(Root_LevelUp_YingXiangLi,new RedPoint(Root_LevelUp_YingXiangLi,this.GetNode(Root_LevelUp)));
      this.m_AllNodes.set(Root_Task,new RedPoint(Root_Task,this.Root));

      this.InitLstNodeTree();
    }

    //Build all end nodes
    InitLstNodeTree()
    {
      this.m_allLastNodes.push(this.GetNode(Root_LevelUp_BiaoYanLi));
      this.m_allLastNodes.push(this.GetNode(Root_LevelUp_BianXianLi));
      this.m_allLastNodes.push(this.GetNode(Root_LevelUp_YingXiangLi));
      this.m_allLastNodes.push(this.GetNode(Root_Task));

      console.log("Initializing red dot tree//")
      console.info(this.m_AllNodes);
      console.info(this.m_allLastNodes);
      console.log("Initialize red dot treeEND//")
    }
//Get node
    GetNode(path:string):RedPoint
    {
      if (path == "") {
        return null;
      }

      const node = this.m_AllNodes.get(path);
      if (node != null || node != undefined) {
        return node;
      }
      else
      {
        return null;
      }
    }
//Modify node value
    ChangeValue(path:string,state:boolean):void
    {
        const _redPoint:RedPoint = this.m_AllNodes.get(path);
        if(_redPoint.GetChilds().length != 0)
        {
            throw new Error("No modification allowed, root node");
        }

        _redPoint.ChangeState(state);
    }

}

business:

Define the root node in advance

The initialization node m_allLastNodes is stored in the last node

import { _decorator, Component, Node } from 'cc';
import { PlayerInfo } from '../Info/PlayerInfo';
import { ExcelMgr } from '../Unit/Excel/Managers/ExcelMgr';
import { RedPointManager, Root_LevelUp_BiaoYanLi, Root_LevelUp_YingXiangLi, Root_LevelUp_BianXianLi } from './RedPointManager';

export class RedCheke extends Component {
    public static Instance: RedCheke = null as unknown as RedCheke;
  
    private _playerInfo:PlayerInfo;
    onLoad(): void {
      if (RedCheke.Instance === null) {
        RedCheke.Instance = this;
      }
      else {
        this.destroy();
        return;
      }
    }

    start() {
       
    }
    public Init(playerinfo:PlayerInfo)
    {
        this._playerInfo = playerinfo;
    }

    //Because there is no delegation, it can only be updated violently.
    private ChekeLevelUp_performance_RedPoint()
    {
      var info1 = ExcelMgr.Instance.queryByID("PlayerLevelUpTable",this._playerInfo.performance_Level.toString());
      var info2 = ExcelMgr.Instance.queryByID("PlayerLevelUpTable",this._playerInfo.influence_Level.toString());
      var info3 = ExcelMgr.Instance.queryByID("PlayerLevelUpTable",this._playerInfo.realization_Level.toString());
      if(info1 & amp; & amp; info2 & amp; & amp; info3)
      {
        var NeedMoney_performance = info1.performance_LevelUp_NeedMoney;
        var NeedMonet_Influence = info2.influence_LevelUp_NeedMoney;
        var NeedMonet_realization = info3.realization_LevelUp_NeedMoney;
      
        RedPointManager.Instance.ChangeValue(Root_LevelUp_BiaoYanLi,(this._playerInfo.Money >= NeedMoney_performance));
        
        RedPointManager.Instance.ChangeValue(Root_LevelUp_YingXiangLi,(this._playerInfo.Money >= NeedMonet_Influence));

        RedPointManager.Instance.ChangeValue(Root_LevelUp_BianXianLi,(this._playerInfo.Money >= NeedMonet_realization));
      }
    }

    privateChekeTask_RedPoint()
    {

    }





    update(deltaTime: number) {
        this.ChekeLevelUp_performance_RedPoint();
       // this.ChekeTask_RedPoint();
    }
}


Player => Make an operation to modify attributes => Call RedCheke to modify the corresponding node => UI gets whether the node is lit or not. Shows and hides the red dot UI.

The business code is too ugly, but that’s what it means

Because there are very few red dot tutorials about cocos on the Internet, most of them are lacking in both east and west. We can only imitate a performance problem according to the red dot system ideas of the two bosses of Unity. It should only be applicable to small games after all. The cocos project is also likely to be a small game

Welcome all the experts to give advice. After all, what I imitated is not the optimal solution.

Thanks to the two big guys from Unity. The stars that herd cows are naturally blessed with cat immortals.