You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity回合制策略游戏角色点击移动方格后偏移到错误位置问题求助

核心问题根因
  • 位移API误用:Transform.Translate() 接收的是相对当前位置的偏移值,你代码中传入的是目标方格的世界坐标,导致最终位置 = 角色当前坐标 + 目标方格坐标,完全不符合预期。
  • 点击事件重复触发:OnMouseOver 中使用 Input.GetKey(KeyCode.Mouse0) 会在按住左键的每帧都执行位移逻辑,单次点击可能触发多次位移叠加,偏移量逐次累加。
  • 移动方格重复生成:units 脚本的 Update 方法中只要角色处于选中状态,每帧都会生成一轮可移动范围方格,同位置会堆叠大量重复MovePlate,点击时多次触发位移,同时会产生冗余性能消耗。
  • 选中提示资源泄漏:选中角色时生成的 tempselect 没有销毁逻辑,每次选中都会新增实例,额外占用资源。
修复代码

MovePlate.cs 修正后内容

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

public class MovePlate : MonoBehaviour
{
    GameObject controller;
    public GameObject reference = null;
    public float x;
    public float y;
    // Start is called before the first frame update
    void Start()
    {
        x = this.transform.position.x;
        y = this.transform.position.y;
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void SetReference(GameObject obj)
    {
        reference = obj;
    }
    public GameObject GetReference()
    {
        return reference;
    }
    public void OnMouseOver()
    {
        // 改用GetKeyDown只触发一次点击,直接赋值世界坐标而非相对偏移
        if(Input.GetKeyDown(KeyCode.Mouse0))
        {
            reference.transform.position = new Vector3(x, y, reference.transform.position.z);
            reference.GetComponent<units>().selected = false;
        }
    }
}

units.cs 修正后内容

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

public class units : MonoBehaviour
{
    public GameObject Select;
    public GameObject movePlate;
    public GameObject tempselect;

    public int movement;
    public bool selected;
    private bool mouseover;
    // Start is called before the first frame update
    void Start()
    {
        selected = false;
        mouseover = false;
    }

    // Update is called once per frame
    void Update()
    {
        if(selected && Input.GetKey(KeyCode.Mouse1))
        {
            selected = false;
        }
        if(!selected)
        {
            DestroyMovePlates();
            // 取消选中时销毁选中提示
            if(tempselect != null)
            {
                Destroy(tempselect);
                tempselect = null;
            }
        }
    }

    // 把移动方格生成逻辑抽成单独方法,只在选中时调用一次
    void SpawnMovePlates()
    {
        for (int i = 1; i < movement + 1; i++)
        {
            Debug.Log("Bacon");
            if (this.gameObject.transform.position.x + i < 20)
            {
                GameObject mp1 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x + i, this.gameObject.transform.position.y, -2), Quaternion.identity);
                mp1.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp1.GetComponent<MovePlate>().x = this.gameObject.transform.position.x + i;
                mp1.GetComponent<MovePlate>().y = this.gameObject.transform.position.y;
            }
            if (this.gameObject.transform.position.x + i < 20 && this.gameObject.transform.position.y + i < 20)
            {
                GameObject mp2 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x + i, this.gameObject.transform.position.y + i, -2), Quaternion.identity);
                mp2.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp2.GetComponent<MovePlate>().x = this.gameObject.transform.position.x + i;
                mp2.GetComponent<MovePlate>().y = this.gameObject.transform.position.y + i;
            }
            if (this.gameObject.transform.position.y + i < 20)
            {
                GameObject mp3 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y + i, -2), Quaternion.identity);
                mp3.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp3.GetComponent<MovePlate>().x = this.gameObject.transform.position.x;
                mp3.GetComponent<MovePlate>().y = this.gameObject.transform.position.y + i;
            }
            if (this.gameObject.transform.position.x - i >= 0 && this.gameObject.transform.position.y + i < 20)
            {
                GameObject mp4 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x - i, this.gameObject.transform.position.y + i, -2), Quaternion.identity);
                mp4.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp4.GetComponent<MovePlate>().x = this.gameObject.transform.position.x - i;
                mp4.GetComponent<MovePlate>().y = this.gameObject.transform.position.y + i;
            }
            if (this.gameObject.transform.position.x - i >= 0)
            {
                GameObject mp5 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x - i, this.gameObject.transform.position.y, -2), Quaternion.identity);
                mp5.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp5.GetComponent<MovePlate>().x = this.gameObject.transform.position.x - i;
                mp5.GetComponent<MovePlate>().y = this.gameObject.transform.position.y;
            }
            if (this.gameObject.transform.position.x + i < 20 && this.gameObject.transform.position.y - i >= 0)
            {
                GameObject mp6 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x + i, this.gameObject.transform.position.y - i, -2), Quaternion.identity);
                mp6.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp6.GetComponent<MovePlate>().x = this.gameObject.transform.position.x + i;
                mp6.GetComponent<MovePlate>().y = this.gameObject.transform.position.y - i;
            }
            if (this.gameObject.transform.position.y - i >= 0)
            {
                GameObject mp7 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y - i, -2), Quaternion.identity);
                mp7.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp7.GetComponent<MovePlate>().x = this.gameObject.transform.position.x;
                mp7.GetComponent<MovePlate>().y = this.gameObject.transform.position.y - i;
            }
            if (this.gameObject.transform.position.x - i >= 0 && this.gameObject.transform.position.y - i >= 0)
            {
                GameObject mp8 = Instantiate(movePlate, new Vector3(this.gameObject.transform.position.x - i, this.gameObject.transform.position.y - i, -2), Quaternion.identity);
                mp8.GetComponent<MovePlate>().SetReference(this.gameObject);
                mp8.GetComponent<MovePlate>().x = this.gameObject.transform.position.x - i;
                mp8.GetComponent<MovePlate>().y = this.gameObject.transform.position.y - i;
            }
        }
    }

    void OnMouseOver()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0)&&!selected)
        {
            tempselect = Instantiate(Select, new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y, -3), Quaternion.identity);
            selected = true;
            // 选中时仅生成一次移动方格
            SpawnMovePlates();
        }
    }
    public void DestroyMovePlates()
    {
        //Destroy old MovePlates
        GameObject[] movePlates = GameObject.FindGameObjectsWithTag("MovePlate");
        for (int i = 0; i < movePlates.Length; i++)
        {
            Destroy(movePlates[i]); //Be careful with this function "Destroy" it is asynchronous
        }
    }
}

替换代码后即可解决位移偏移、硬编码位置异常、多次移动坐标累加的问题,同时避免了重复生成对象的性能损耗。

内容的提问来源于stack exchange,提问作者user2420395

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:27:00