//Detect if there is an obstacle in front of the character
        private void DetectFronted()
        {
            float radius = destruct.hit_range * 2f;

            Vector3 center = destruct.GetCenter();
            Vector3 dir    = move_target_avoid - transform.position;
            Vector3 dirl   = Quaternion.AngleAxis(-45f, Vector3.up) * dir.normalized;
            Vector3 dirr   = Quaternion.AngleAxis(45f, Vector3.up) * dir.normalized;

            RaycastHit h, hl, hr;
            bool       fc = PhysicsTool.RaycastCollision(center, dir.normalized * radius, out h);
            bool       fl = PhysicsTool.RaycastCollision(center, dirl.normalized * radius, out hl);
            bool       fr = PhysicsTool.RaycastCollision(center, dirr.normalized * radius, out hr);

            is_fronted_center = fc && (target == null || h.collider.gameObject != target);
            is_fronted_left   = fl && (target == null || hl.collider.gameObject != target);
            is_fronted_right  = fr && (target == null || hr.collider.gameObject != target);

            int front_count = (fc ? 1 : 0) + (fl ? 1 : 0) + (fr ? 1 : 0);

            front_dist = (fc ? h.distance : 0f) + (fl ? hl.distance : 0f) + (fr ? hr.distance : 0f);
            if (front_count > 0)
            {
                front_dist = front_dist / (float)front_count;
            }

            is_fronted = is_fronted_center || is_fronted_left || is_fronted_right;
        }
        private void DoAttackStrike(Destructible target, bool is_ranged)
        {
            //Ranged attack
            ItemData equipped = character.EquipData.GetEquippedWeaponData();

            if (target != null && is_ranged && equipped != null)
            {
                InventoryItemData projectile_inv = character.Inventory.GetFirstItemInGroup(equipped.projectile_group);
                ItemData          projectile     = ItemData.Get(projectile_inv?.item_id);
                if (projectile != null && CanWeaponAttackRanged(target))
                {
                    character.Inventory.UseItem(projectile, 1);
                    Vector3    pos     = GetProjectileSpawnPos();
                    Vector3    dir     = target.GetCenter() - pos;
                    GameObject proj    = Instantiate(projectile.projectile_prefab, pos, Quaternion.LookRotation(dir.normalized, Vector3.up));
                    Projectile project = proj.GetComponent <Projectile>();
                    project.shooter = character;
                    project.dir     = dir.normalized;
                    project.damage  = equipped.damage;
                }
            }

            //Melee attack
            else if (IsAttackTargetInRange(target))
            {
                target.TakeDamage(character, GetAttackDamage(target));

                if (onAttackHit != null)
                {
                    onAttackHit.Invoke(target);
                }
            }
        }