瓦尔海姆的部队战争和agar.io

瓦尔海姆的部队战争和agar.io

部队球球大作战与战争的想法

enemy ai



using UnityEngine;
using UnityEngine.AI;

public class EnemyAI : MonoBehaviour
{

    public NavMeshAgent agent;


    [Header("Orb Searching")]
    public float searchRange = 100f;

    [Header("Orb Collection")]
    public float collectDistance = 2f;
    private Transform targetOrb;

    private OrbCollector collector;



    void Start()
    {

        agent = GetComponent<NavMeshAgent>();

        collector = GetComponent<OrbCollector>();

        if(collector == null)
        {
            Debug.LogWarning(
            "Enemy needs an OrbCollector component!");
        }


        InvokeRepeating(
        "FindOrb",
        0,
        2);
    }





    void Update()
    {

        if(targetOrb != null)
        {

            agent.SetDestination(
            targetOrb.position);


            float distance =
            Vector3.Distance(
            transform.position,
            targetOrb.position);


            if(distance <= collectDistance)
            {

                CollectOrb();

            }
        }
    }





    void FindOrb()
    {

        GameObject[] orbs =
        GameObject.FindGameObjectsWithTag("Orb");

        float closest =
        Mathf.Infinity;

        GameObject best = null;


        foreach(GameObject orb in orbs)
        {

            float distance =
            Vector3.Distance(
            transform.position,
            orb.transform.position);


            if(distance < closest &&
            distance <= searchRange)
            {

                closest = distance;
                best = orb;
            }
        }


        if(best != null)
        {

            targetOrb =
            best.transform;
        }
    }





    void CollectOrb()
    {

        if(collector != null)
        {

            collector.CollectOrb(1);
        }

        Destroy(
        targetOrb.gameObject);


        targetOrb = null;
    }
}



end




enemy spawn



using UnityEngine;

public class EnemySpawner : MonoBehaviour
{

    public GameObject enemyPrefab;

    public Terrain terrain;

    public int enemyAmount = 50;


    void Start()
    {
        SpawnEnemies();
    }


    void SpawnEnemies()
    {
        TerrainData data =
        terrain.terrainData;

        Vector3 terrainPos =
        terrain.transform.position;


        for(int i = 0; i < enemyAmount; i++)
        {


            float x =
            Random.Range(
            0,
            data.size.x);


            float z =
            Random.Range(
            0,
            data.size.z);


            float y =
            data.GetHeight(
            (int)x,
            (int)z);


            Vector3 spawn =
            new Vector3(
            x,
            y,
            z)
            + terrainPos;


            Instantiate(
            enemyPrefab,
            spawn,
            Quaternion.identity);

        }
    }
}




end





orb




using UnityEngine;
public class Orb : MonoBehaviour
{
    public int orbValue = 1;
    public float rotateSpeed = 100f;
    private void Update()
    {
        transform.Rotate(Vector3.up * rotateSpeed * Time.deltaTime);
    }

    private void OnTriggerEnter(Collider other)
    {
        OrbCollector collector = other.GetComponent<OrbCollector>();
        if (collector != null)
        {
            collector.CollectOrb(orbValue);
            Destroy(gameObject);
        }
    }
}




end





orb collector



using UnityEngine;

public class OrbCollector : MonoBehaviour
{

    [Header("Collector")]
    public string collectorName;

    [Header("Orb Storage")]
    public int orbs = 0;


    [Header("Troop Spawning")]
    public GameObject troopPrefab;
    public Transform troopSpawnPoint;
    public int orbsPerTroop = 5;

    public int troopsSpawned = 0;


    public void CollectOrb(int amount)
    {

        orbs += amount;

        Debug.Log(
        collectorName +
        " has " +
        orbs +
        " orbs");

        CheckSpawn();
    }





    void CheckSpawn()
    {

        while(orbs >= orbsPerTroop)
        {

            SpawnTroop();

            orbs -= orbsPerTroop;
        }
    }





    void SpawnTroop()
    {

        if(troopPrefab == null)
        {
            Debug.LogWarning(
            "No troop prefab assigned");
            return;
        }


        Vector3 spawnPosition;


        if(troopSpawnPoint != null)
        {
            spawnPosition =
            troopSpawnPoint.position;
        }
        else
        {
            spawnPosition =
            transform.position +
            transform.forward * 3;
        }


        GameObject troop =
        Instantiate(
        troopPrefab,
        spawnPosition,
        Quaternion.identity);


        TroopAI ai =
        troop.GetComponent<TroopAI>();


        if(ai != null)
        {
            ai.owner =
            transform;
        }


        troopsSpawned++;

        Debug.Log(
        "Spawned troop " +
        troopsSpawned);
    }
}



end




orb spawn





using UnityEngine;

public class OrbSpawner : MonoBehaviour
{
    public GameObject orbPrefab;
    public Terrain terrain;

    public int amount = 200;

    public float heightOffset = 1f;

    void Start()
    {
        SpawnAllOrbs();
    }


    void SpawnAllOrbs()
    {
        if(terrain == null)
        {
            Debug.LogError("No terrain assigned");
            return;
        }

        TerrainData data = terrain.terrainData;

        Vector3 terrainPosition =
        terrain.transform.position;


        for(int i = 0; i < amount; i++)
        {

            float x =
            Random.Range(
            0,
            data.size.x);

            float z =
            Random.Range(
            0,
            data.size.z);


            float y =
            data.GetHeight(
            (int)x,
            (int)z);


            Vector3 position =
            new Vector3(
            x,
            y + heightOffset,
            z)
            + terrainPosition;


            Instantiate(
            orbPrefab,
            position,
            Quaternion.identity);
        }
    }
}




end





troop ai



using UnityEngine;
using UnityEngine.AI;

public class TroopAI : MonoBehaviour
{
    [Header("Owner")]
    public Transform owner;

    [Header("Movement")]
    public NavMeshAgent agent;

    public float followDistance = 5f;
    public float updateRate = 0.5f;
    [Header("Combat")]
    public float health = 100;

    public float damage = 10;
    private float timer;

    void Start()
    {
        agent =
        GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        if(owner == null)
        {
            return;
        }

        timer += Time.deltaTime;

        if(timer >= updateRate)
        {
            FollowOwner();

            timer = 0;
        }
    }

    void FollowOwner()
    {
        float distance =
        Vector3.Distance(
        transform.position,
        owner.position);

        if(distance > followDistance)
        {
            agent.SetDestination(
            owner.position);
        }
        else
        {
            agent.ResetPath();
        }
    }

    public void TakeDamage(float amount)
    {
        health -= amount;

        if(health <= 0)
        {
            Destroy(gameObject);
        }
    }
}



end




view


using UnityEngine;
using System.Collections.Generic;

public class EnemyWatchCamera : MonoBehaviour
{
    [Header("Camera")]
    public Camera playerCamera;
    public Camera watchCamera;

    [Header("AI Settings")]
    public string aiTag = "Enemy";

    public float orbitDistance = 6f;
    public float orbitHeight = 3f;
    public float orbitSpeed = 120f;

    [Header("Controls")]
    public KeyCode watchKey = KeyCode.V;
    public KeyCode nextTargetKey = KeyCode.C;


    private List<GameObject> targets = new List<GameObject>();

    private int currentTarget = 0;

    private bool watching = false;

    private float orbitAngle;


    void Start()
    {
        watchCamera.enabled = false;
        playerCamera.enabled = true;

        FindTargets();
    }


    void Update()
    {

        if(Input.GetKeyDown(watchKey))
        {
            ToggleWatch();
        }

        if(watching && Input.GetKeyDown(nextTargetKey))
        {
            NextTarget();
        }

        if(watching)
        {
            OrbitCamera();
        }
    }


    void FindTargets()
    {
        targets.Clear();

        GameObject[] enemies = GameObject.FindGameObjectsWithTag(aiTag);

        foreach(GameObject enemy in enemies)
        {
            targets.Add(enemy);
        }
    }


    void ToggleWatch()
    {

        watching = !watching;

        if(watching)
        {
            FindTargets();
            playerCamera.enabled = false;
            watchCamera.enabled = true;

            currentTarget = 0;
        }
        else
        {
            watchCamera.enabled = false;
            playerCamera.enabled = true;
        }

    }


    void NextTarget()
    {

        FindTargets();

        if(targets.Count == 0)
            return;

        currentTarget++;

        if(currentTarget >= targets.Count)
        {
            currentTarget = 0;
        }

    }


    void OrbitCamera()
    {

        if(targets.Count == 0)
            return;

        GameObject target = targets[currentTarget];

        if(target == null)
            return;


        orbitAngle += Input.GetAxis("Mouse X") * orbitSpeed * Time.deltaTime;

        Vector3 offset = new Vector3(
            Mathf.Sin(orbitAngle * Mathf.Deg2Rad) * orbitDistance,
            orbitHeight,
            Mathf.Cos(orbitAngle * Mathf.Deg2Rad) * orbitDistance
        );


        watchCamera.transform.position =
            target.transform.position + offset;

        watchCamera.transform.LookAt(
            target.transform.position + Vector3.up
        );

    }
}



end



obelisk



using UnityEngine;
using System.Collections.Generic;

public class TerrainObeliskSpawner : MonoBehaviour
{
    [Header("Terrain")]
    public Terrain terrain;


    [Header("Obelisk Prefab")]
    public GameObject obeliskPrefab;


    [Header("Spawn Settings")]
    public int amountToSpawn = 20;

    public float minDistanceBetweenObelisks = 50f;
    public float spawnHeightOffset = 1f;


    [Header("Lifetime")]
    public bool enableDecay = true;

    public float decayTime = 300f;
    public float respawnTime = 60f;


    private List<GameObject> spawnedObelisks = new List<GameObject>();

    void Start()
    {
        SpawnObelisks();
    }


    public void SpawnObelisks()
    {
        int attempts = 0;
        int maxAttempts = amountToSpawn * 50;

        while (spawnedObelisks.Count < amountToSpawn && attempts < maxAttempts)
        {
            attempts++;


            Vector3 spawnPosition = GetRandomTerrainPosition();

            if (IsValidPosition(spawnPosition))
            {
                GameObject obelisk = Instantiate(
                    obeliskPrefab,
                    spawnPosition,
                    Quaternion.identity
                );


                spawnedObelisks.Add(obelisk);

                if(enableDecay)
                {
                    StartCoroutine(DecayObelisk(obelisk));
                }
            }
        }
    }


    Vector3 GetRandomTerrainPosition()
    {
        Vector3 terrainSize = terrain.terrainData.size;

        float x = Random.Range(0, terrainSize.x);
        float z = Random.Range(0, terrainSize.z);

        float y = terrain.SampleHeight(
            new Vector3(x,0,z)
        );

        return terrain.transform.position +
        new Vector3(
            x,
            y + spawnHeightOffset,
            z
        );
    }


    bool IsValidPosition(Vector3 position)
    {
        foreach(GameObject obj in spawnedObelisks)
        {
            if(obj == null)
                continue;


            float distance = Vector3.Distance(
                position,
                obj.transform.position
            );

            if(distance < minDistanceBetweenObelisks)
                return false;
        }


        return true;
    }


    System.Collections.IEnumerator DecayObelisk(GameObject obelisk)
    {
        yield return new WaitForSeconds(decayTime);

        if(obelisk != null)
        {
            spawnedObelisks.Remove(obelisk);
            Destroy(obelisk);
        }

        yield return new WaitForSeconds(respawnTime);

        SpawnSingleObelisk();
    }


    void SpawnSingleObelisk()
    {
        int attempts = 0;

        while(attempts < 100)
        {
            attempts++;

            Vector3 pos = GetRandomTerrainPosition();

            if(IsValidPosition(pos))
            {
                GameObject obelisk = Instantiate(
                    obeliskPrefab,
                    pos,
                    Quaternion.identity
                );

                spawnedObelisks.Add(obelisk);

                if(enableDecay)
                    StartCoroutine(DecayObelisk(obelisk));


                break;
            }
        }
    }
}



end






room 




using UnityEngine;
using System.Collections;

public class ObeliskRoomInterior : MonoBehaviour
{
    [Header("Player")]
    public Transform player;
    [Header("Room Prefab")]
    public GameObject roomPrefab;
    [Header("Room Settings")]
    public Transform outsideExitPoint;

    public float enterDistance = 4f;

    public float roomDepth = -500f;

    [Header("Spawn Protection")]
    public float spawnHeightOffset = 1.5f;
    public float teleportDelay = 0.1f;


    [Header("Terrain Border")]
    public Terrain terrain;
    public float borderDistance = 30f;


    [Header("Input")]
    public KeyCode enterKey = KeyCode.E;
    public KeyCode exitKey = KeyCode.F;


    private GameObject spawnedRoom;

    private bool playerInside = false;


    void Update()
    {
        if (!playerInside)
        {
            float distance = Vector3.Distance(
                player.position,
                transform.position
            );

            if(distance <= enterDistance)
            {
                if(Input.GetKeyDown(enterKey))
                {
                    EnterRoom();
                }
            }
        }
        else
        {
            if(Input.GetKeyDown(exitKey))
            {
                ExitRoom();
            }
        }
    }


    void EnterRoom()
    {
        playerInside = true;

        Vector3 roomPosition = new Vector3(
            transform.position.x,
            roomDepth,
            transform.position.z
        );

        // 保持房间远离地形边界
        if(terrain != null)
        {
            Vector3 terrainPos = terrain.transform.position;
            Vector3 terrainSize = terrain.terrainData.size;


            roomPosition.x = Mathf.Clamp(
                roomPosition.x,
                terrainPos.x + borderDistance,
                terrainPos.x + terrainSize.x - borderDistance
            );

            roomPosition.z = Mathf.Clamp(
                roomPosition.z,
                terrainPos.z + borderDistance,
                terrainPos.z + terrainSize.z - borderDistance
            );
        }


        spawnedRoom = Instantiate(
            roomPrefab,
            roomPosition,
            Quaternion.identity
        );

        ObeliskRoomExit exit =
            spawnedRoom.GetComponentInChildren<ObeliskRoomExit>();

        if(exit != null)
        {
            exit.owner = this;
            exit.player = player;
            exit.outsidePosition = outsideExitPoint.position;
        }

        Transform insideSpawn =
            spawnedRoom.transform.Find("InsideSpawn");

        if(insideSpawn != null)
        {
            StartCoroutine(TeleportInside(insideSpawn));
        }
        else
        {
            StartCoroutine(TeleportInside(spawnedRoom.transform));
        }
    }


    IEnumerator TeleportInside(Transform spawn)
    {
        // 等待房间碰撞体加载
        yield return new WaitForSeconds(teleportDelay);

        CharacterController controller =
            player.GetComponent<CharacterController>();

        if(controller != null)
        {
            controller.enabled = false;
        }

        player.position = spawn.position + Vector3.up * spawnHeightOffset;

        if(controller != null)
        {
            controller.enabled = true;
        }
    }


    public void ExitRoom()
    {
        playerInside = false;

        CharacterController controller =
            player.GetComponent<CharacterController>();

        if(controller != null)
        {
            controller.enabled = false;
        }

        player.position = outsideExitPoint.position;

        if(controller != null)
        {
            controller.enabled = true;
        }

        if(spawnedRoom != null)
        {
            Destroy(spawnedRoom);
        }
    }
}





end




room exit



using UnityEngine;

public class ObeliskRoomExit : MonoBehaviour
{

    [HideInInspector]
    public ObeliskRoomInterior owner;

    [HideInInspector]
    public Transform player;

    public Vector3 outsidePosition;

    public KeyCode exitKey = KeyCode.F;


    void Update()
    {
        if(player == null)
            return;

        float distance =
            Vector3.Distance(
                player.position,
                transform.position
            );

        if(distance < 3f)
        {

            if(Input.GetKeyDown(exitKey))
            {
                Exit();
            }

        }
    }


    void Exit()
    {

        owner.ExitRoom();

    }

}



end



troop storage




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

public class SimpleObeliskTroopStorage : MonoBehaviour
{

    [Header("Storage")]
    public int maxTroops = 20;
    public float storageRange = 5f;


    [Header("Release")]
    public float releaseDistance = 2f;


    [Header("Controls")]
    public KeyCode storeKey = KeyCode.G;
    public KeyCode releaseKey = KeyCode.R;


    private List<GameObject> storedTroops = new List<GameObject>();


    void Update()
    {

        if(Input.GetKeyDown(storeKey))
        {
            StoreTroop();
        }

        if(Input.GetKeyDown(releaseKey))
        {
            ReleaseTroop();
        }

    }





    void StoreTroop()
    {

        if(storedTroops.Count >= maxTroops)
        {
            Debug.Log("方尖碑存储已满");
            return;
        }


        Collider[] nearby =
        Physics.OverlapSphere(
            transform.position,
            storageRange
        );


        foreach(Collider col in nearby)
        {

            TroopAI troop =
            col.GetComponentInParent<TroopAI>();

            if(troop != null)
            {

                GameObject troopObject =
                troop.gameObject;


                storedTroops.Add(troopObject);


                troopObject.SetActive(false);


                Debug.Log(
                "已存储部队: "
                + troopObject.name
                );

                return;
            }
        }


        Debug.Log("附近没有部队");
    }







    void ReleaseTroop()
    {

        if(storedTroops.Count == 0)
        {
            Debug.Log("没有已存储的部队");
            return;
        }


        GameObject troop =
        storedTroops[0];

        storedTroops.RemoveAt(0);


        Vector3 spawnPosition =
        transform.position +
        transform.forward * releaseDistance;


        troop.transform.position =
        spawnPosition;

        troop.transform.rotation =
        transform.rotation;

        troop.SetActive(true);

        NavMeshAgent agent =
        troop.GetComponent<NavMeshAgent>();

        if(agent != null)
        {

            agent.enabled = true;
            agent.Warp(spawnPosition);
        }

        Debug.Log(
        "已释放部队: "
        + troop.name
        );
    }






    public int GetStoredTroopCount()
    {
        return storedTroops.Count;
    }




    void OnDrawGizmosSelected()
    {
        Gizmos.DrawWireSphere(
            transform.position,
            storageRange
        );
    }

}



end