protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            //---------check if we need to run---------//
            var entSchedule = GetSingletonEntity <CpSysSchedule>();
            var cpSchedule  = GetSingleton <CpSysSchedule>();

            if (!cpSchedule.CanRunSysUpdateAtt())
            {
                return(inputDeps);
            }

            _lastRunFrame = Time.frameCount;
            var em = World.Active.EntityManager;

            //---------preapre---------//
            is_converge_arr[0] = true;
            int cnt_relation = _group_rel.CalculateLength();

            var access_att_ro   = GetComponentDataFromEntity <CpAttitude>(isReadOnly: true);
            var access_att_rw   = GetComponentDataFromEntity <CpAttitude>();
            var access_schedule = GetComponentDataFromEntity <CpSysSchedule>();
            var access_dirty    = GetComponentDataFromEntity <CpIsDirty>(isReadOnly: false);
            var accbuf_relation = GetBufferFromEntity <CpRelationBuf>(isReadOnly: true);

            //---------run---------//

            //---------collect modifications---------//
            var jobCollect = new CollectJob {
                acc_att         = access_att_ro,
                is_converge_arr = is_converge_arr,
                orig_attitudes  = orig_attitudes.ToConcurrent(),
                target_mods     = target_mods.ToConcurrent(),
                unique_nodes    = unique_nodes.ToConcurrent(),
            }.Schedule(this, inputDeps);

            var jobCheckConverge = new CheckConvergeJob {
                is_converge_arr = is_converge_arr,
                entSchedule     = entSchedule,
                acc_schedule    = access_schedule,
            }.Schedule(jobCollect);

            //---------assign back to attitudes---------//
            var jobWriteBack = new WriteBackJob {
                acc_att = access_att_rw,
            }.Schedule(target_mods, 1, jobCollect);

            var jobClearTargetMods = target_mods.ClearWithJob(jobWriteBack);

            var jobSetDirtyNode = new SetDirtyByTargetNodes {
                orig_attitude   = orig_attitudes,
                accbuf_relation = accbuf_relation,
                acc_att         = access_att_ro,
                acc_dirty       = access_dirty,
                NODE_THRES      = NODE_MOD_THRES,
            }.Schedule(unique_nodes, 8, jobWriteBack);

            var jobClearUniqueNodes  = unique_nodes.ClearWithJob(jobSetDirtyNode);
            var jobClearOrigAttitude = orig_attitudes.ClearWithJob(jobSetDirtyNode);

            var handle_clear = JobHandle.CombineDependencies(jobClearTargetMods, jobClearUniqueNodes, jobClearOrigAttitude);

            return(JobHandle.CombineDependencies(handle_clear, jobCheckConverge));
        }