当前位置:   article > 正文

unity实现自定义位置添加备注(文字)功能_unity如何实现打字映射到物品上

unity如何实现打字映射到物品上

公司经营的软件与绘图相关,这天,客户提出来一个需求,希望能在绘图的任意位置添加备注,方便厂家之间沟通。
客户要求:可以在任意位置添加、修改、删除。
实现过程:
1、如何创建?
这个问题很简单,UI界面添加一个Button,绑定一个事件,点击的时候创建一个游戏物体专门用来显示文字。显示文字使用TextMesh组件,如下图:
在这里插入图片描述
2、如何修改文字?
这个问题也很容易解决,添加一个inputfiled组件,获取用户输入的文本,然后再将用户输入的内容传递给TextMesh即可。
3、如何实现移动这些文字?
给每个物体添加一个脚本,跟随鼠标或者手势滑动的位置。代码如下:

public class Move : MonoBehaviour {
    Ray ray;
    Vector3 position;
    RaycastHit hit;
    //判断当前是否被选中
    public bool isSelect=true;
    void LateUpdate()
    {
        if (Input.GetMouseButton(0)&& isSelect)
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.transform.gameObject.tag == "Note")
                {
                    transform.position = hit.point;
                }
            }
        }
        if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved&& isSelect)
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.transform.gameObject.tag == "Note")
                {
                    transform.position = hit.point;
                }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

4、如何知道客户想修改的是哪一个文本?
创建一个控制脚本,里面定义一个空物体,作为当前物体的引用。使用射线,获取当前用户点击到的文本,拿到当前用户点击的物体,当用户点击另一个的时候,将当前物体的引用改为新点击的即可。代码细节如下:

public class Test : MonoBehaviour {

    GameObject currentObj;

    Ray ray;

    RaycastHit hit;

    public GameObject parentObj;

    public InputField InputField;

    public Button OKButton;

    public Button createButton;

    public Button delButton;

    private Color black;
    //当前被选中的为黄色
    private Color yellow;
    
    void Start () {
        black = new Color(0, 0, 0);
        yellow = new Color(215, 215, 0);
        OKButton.onClick.AddListener(() => ReviseText());
        createButton.onClick.AddListener(() => CreateNote());
        delButton.onClick.AddListener(()=>Del());
    }
    void CreateNote()
    {
        Resert();
        GameObject obj = new GameObject("Test");
        currentObj = obj;
        var textMesh = obj.AddComponent<TextMesh>();
        textMesh.text = "测试字体";
        textMesh.fontSize = 100;
        obj.transform.SetParent(transform);
        obj.transform.localPosition = new Vector3(0, 0, 100);
        obj.transform.SetParent(parentObj.transform);
        obj.tag = "Note";
        obj.GetComponent<TextMesh>().color = yellow;
        obj.GetComponent<TextMesh>().anchor = TextAnchor.MiddleCenter;
        obj.AddComponent<Move>();
        obj.GetComponent<Move>().isSelect = true;
        //TextMeshPro插件添加碰撞体不会随着字体改变而改变,所以最后添加
        obj.AddComponent<BoxCollider>();

    }
    //重置上一个选中的状态
    private void Resert()
    {
        //将先前选中的备注设置为黑色
        if (currentObj != null)
        {
            currentObj.GetComponent<TextMesh>().color = black;
            currentObj.GetComponent<Move>().isSelect = false;
        }
    }

    void ReviseText()
    {
        if (currentObj!=null)
        {
            currentObj.GetComponent<TextMesh>().text = InputField.text;
            //TextMeshPro插件添加碰撞体不会随着字体改变而改变,所以需要删除后重新添加
            Destroy(currentObj.GetComponent<BoxCollider>());
            currentObj.AddComponent<BoxCollider>();
        }
    }
    void Del()
    {
        if (currentObj != null)
            Destroy(currentObj);
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.transform.gameObject.tag == "Note")
                {
                    if (currentObj != null)
                    {
                        currentObj.GetComponent<TextMesh>().color = black;
                        currentObj.GetComponent<Move>().isSelect = false;
                    }
                    currentObj = hit.transform.gameObject;
                    currentObj.GetComponent<TextMesh>().color = yellow;
                    currentObj.GetComponent<Move>().isSelect = true;
                }
            }
        }
        if(Input.touchCount==1&&Input.GetTouch(0).phase == TouchPhase.Began)
        {
            ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.transform.gameObject.tag == "Note")
                {
                    Resert();
                    currentObj = hit.transform.gameObject;
                    currentObj.GetComponent<TextMesh>().color = yellow;
                    currentObj.GetComponent<Move>().isSelect = true;
                }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

效果如下:在这里插入图片描述

总结:总的来说还是一个比较简单易实现的小功能,主要用到Input类射线类

后续:实际应用的时候可以创建一个空物体作为预制件,提前添加好需要用到的脚本,实际开发调用的时候可以减少代码量,提高阅读效率。

2020.8.26后续更新,客户画的图有大有小,希望可以自定义字体的大小,看起来更搭配。
新增一个Slider组件,通过这个滑动轴来定义大小。
在测试脚本中给Slider组件添加事件。

        slider.onValueChanged.AddListener((value)=> 
        {
            if (currentObj != null)
                currentObj.transform.localScale = new Vector3(value,value,value);
        });
  • 1
  • 2
  • 3
  • 4
  • 5

为了客户的更好使用,客户点击到每一个字体的时候,这个时候Slider的value应该改为当前值。
分别在创建新字体和点击字体时候调用。

    //重置滑块的Value值
    private void ResetSliderValue()
    {
        slider.value = currentObj.transform.localScale.x;
    }
  • 1
  • 2
  • 3
  • 4
  • 5

实际效果:
在这里插入图片描述
客户在提完改变大小的要求后,希望能增加多种颜色自由选择。简单想了一下,解决方法有俩。
1:调用调色板(比较复杂,而且不知道手机上是否支持,暂且放弃,百度可以搜索到相关方法,是可行的)
2:使用DropDown组件。将常用颜色放入到下拉框中,供客户选择。
UI界面设置如下:
在这里插入图片描述
代码添加事件即可。

        dropdown.onValueChanged.AddListener((value) =>
        {
            if (currentObj != null)
            {
                switch (value)
                {
                    case 0:
                        currentObj.GetComponent<TextMesh>().color = Color.green;
                        break;
                    case 1:
                        currentObj.GetComponent<TextMesh>().color = Color.blue;
                        break;
                    case 2:
                        currentObj.GetComponent<TextMesh>().color = Color.red;
                        break;
                }
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

实际效果:在这里插入图片描述
但是UGUI默认的DropDown有若干个问题。
1、下拉菜单弹出时,首选项(即第一个)是被选中的状态。此时调用首选项无效。
2、如果上次选择了某一项,下一次还是选择这个,不会执行OnVlaueChanged事件。(这个很致命,用户有时候会挨个设置一样的颜色,结果发现无效)。
改进方法:看UGUI源码,自己做一个DropDown组件。(挖个坑,有空的时候回来填坑)。
9.3后续更新。
选中字体的时候,字体的position会直接改为点击的位置,这就造成了点击字体的位置不是中心位置的时候会造成便宜,需要优化,优化代码如下。
移动脚本中增加一个偏移量。

    public Vector3 pianyi;
  • 1

点击的时候计算下偏移量,然后用点击的位置减去原来的位置再减去偏移量,就可以得到鼠标移动的距离,用原来的坐标位置加上移动的距离即可。
移动脚本代码,写在lateupdate中

transform.position +=  new Vector3(hit.point.x - transform.position.x - pianyi.x, hit.point.y - transform.position.y - pianyi.y, 0);
  • 1

测试脚本代码

currentObj.GetComponent<Move>().pianyi = hit.point - currentObj.transform.position;
  • 1

优化后的效果:
在这里插入图片描述
Demo

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/542836
推荐阅读
相关标签
  

闽ICP备14008679号