Unity之物体触碰墙面后随机方向移动

目录

一、效果图

二、脚本思路

1.随机方向

 2.物体移动

3.墙壁检测

三、界面布局

一、效果图

二、脚本思路

1.随机方向

利用父物体旋转移动会影响其子物体的特性制作,在场景中创建三个物体一个用于移动的物体Obj,一个用于旋转的“标杆”物体 pole,一个是负责记录方向的点 Point 物体,其中Point是pole的父物体,Obj是pole父物体,界面布局如下:

当我们旋转pole的z轴时,其子物体 Point的位置方向就会改变。

脚本如下: 

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


/// <summary>
/// 随机移动效果
/// </summary>
public class BaseRandomMove : MonoBehaviour
{
  
    [Header("指针方向")]
    [SerializeField] Transform pole; //标杆(负责旋转)
    [SerializeField] Transform pointDis; //点位方向(物体移动方向)注意:点的位置要超出墙的包裹范围



    void Start()
    {
        //默认隐藏标杆
        pole.gameObject.SetActive(false);
        RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向

    }

    void Update()
    {

        //绘制线条
        Debug.DrawLine(transform.position, pointDis.position, Color.red);


        //按下测试
        if (Input.GetKeyDown(KeyCode.A))
        {
            RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
        }
    }

    #region 随机转向
    /// <summary>
    /// 随机方向
    /// </summary>
    /// <param name="min">最小值</param>
    /// <param name="max">最大值</param>
    /// <param name="max">旋转轴设置 不旋转 Vector3(0,0,0),所有轴旋转Vector3(1,1,1)</param>
    void RandomDirection(float min, float max, Vector3 normalAngle)
    {
        normalAngle = new Vector3(Mathf.Clamp(normalAngle.x, 0, 1), Mathf.Clamp(normalAngle.y, 0, 1), Mathf.Clamp(normalAngle.z, 0, 1)); //旋转轴归一化
        float angle = UnityEngine.Random.Range(min, max);//随机旋转

        pole.localRotation = Quaternion.Euler(normalAngle * angle); //旋转标杆
    }
    #endregion

   

}

 2.物体移动

获取到移动方向后直接使用 Vector3.MoveTowards来控制移动

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


/// <summary>
/// 随机移动效果
/// </summary>
public class BaseRandomMove : MonoBehaviour
{
    Vector3 originalPos; //文字原位置

    [SerializeField] float speed = 3; //速度

    [Header("指针方向")]
    [SerializeField] Transform pole; //标杆(负责旋转)
    [SerializeField] Transform pointDis; //点位方向(物体移动方向)注意:点的位置要超出墙的包裹范围


    void Start()
    {
        //默认隐藏标杆
        pole.gameObject.SetActive(false);

        originalPos = transform.position; //记录原点位置
        RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向


    }

    void Update()
    {
         //绘制线条
        Debug.DrawLine(transform.position, pointDis.position, Color.red);
        transform.position = Vector3.MoveTowards(transform.position, pointDis.position, speed * Time.deltaTime);


        //按下测试
        if (Input.GetKeyDown(KeyCode.A))
        {
            RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
        }
    }

    #region 随机转向
    /// <summary>
    /// 随机方向
    /// </summary>
    /// <param name="min">最小值</param>
    /// <param name="max">最大值</param>
    /// <param name="max">旋转轴设置 不旋转 Vector3(0,0,0),所有轴旋转Vector3(1,1,1)</param>
    void RandomDirection(float min, float max, Vector3 normalAngle)
    {
        normalAngle = new Vector3(Mathf.Clamp(normalAngle.x, 0, 1), Mathf.Clamp(normalAngle.y, 0, 1), Mathf.Clamp(normalAngle.z, 0, 1)); //旋转轴归一化
        float angle = UnityEngine.Random.Range(min, max);//随机旋转

        pole.localRotation = Quaternion.Euler(normalAngle * angle); //旋转标杆
    }
    #endregion



}

3.墙壁检测

将xyz三个轴的数据使用类RestrictedDirection2数据存储。

完整脚本: 

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

/// <summary>
/// 范围位置
/// </summary>
[Serializable]
public class RestrictedDirection2
{
    public bool isEnable = true; //true启用 false禁用
    public float min;
    public float max;
}
/// <summary>
/// 随机移动效果
/// </summary>
public class BaseRandomMove : MonoBehaviour
{
    Vector3 originalPos; //文字原位置

    [SerializeField] float speed = 3; //速度

    [Header("指针方向")]
    [SerializeField] Transform pole; //标杆(负责旋转)
    [SerializeField] Transform pointDis; //点位方向(物体移动方向)注意:点的位置要超出墙的包裹范围

    [Header("范围限制距离(LocalPosition)")]
    [SerializeField] RestrictedDirection2 xPos;
    [SerializeField] RestrictedDirection2 yPos;
    [SerializeField] RestrictedDirection2 zPos;

    void Start()
    {
        //默认隐藏标杆
        //pole.gameObject.SetActive(false);
        speed = float.Parse(ConfigFile.LoadString("CorruptionTextSpeed")); //从配置文件获取速度

        originalPos = transform.position; //记录原点位置
        RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向


    }

    void Update()
    {
        Debug.DrawLine(transform.position, pointDis.position, Color.red);
        transform.position = Vector3.MoveTowards(transform.position, pointDis.position, speed * Time.deltaTime);

        CheckWall();//检测是否碰到墙壁


        //按下测试
        if (Input.GetKeyDown(KeyCode.A))
        {
            RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
        }
    }

    #region 随机转向
    /// <summary>
    /// 随机方向
    /// </summary>
    /// <param name="min">最小值</param>
    /// <param name="max">最大值</param>
    /// <param name="max">旋转轴设置 不旋转 Vector3(0,0,0),所有轴旋转Vector3(1,1,1)</param>
    void RandomDirection(float min, float max, Vector3 normalAngle)
    {
        normalAngle = new Vector3(Mathf.Clamp(normalAngle.x, 0, 1), Mathf.Clamp(normalAngle.y, 0, 1), Mathf.Clamp(normalAngle.z, 0, 1)); //旋转轴归一化
        float angle = UnityEngine.Random.Range(min, max);//随机旋转

        pole.localRotation = Quaternion.Euler(normalAngle * angle); //旋转标杆
    }
    #endregion

    #region 检测是否碰到墙壁
    bool isDiversion;//是否转向
    bool xIsDir; //x轴是否超出距离
    bool yIsDir; //y轴是否超出距离
    bool zIsDir; //z轴是否超出距离
    void CheckWall()
    {
        isDiversion = false;//是否超出距离
        Vector3 newPos = transform.localPosition;

        //检测轴是否超出距离
        xIsDir = xPos.isEnable && (transform.localPosition.x < xPos.min || transform.localPosition.x > xPos.max);
        yIsDir = yPos.isEnable && (transform.localPosition.y < yPos.min || transform.localPosition.y > yPos.max);
        zIsDir = zPos.isEnable && (transform.localPosition.z < zPos.min || transform.localPosition.z > zPos.max);

        isDiversion = xIsDir || yIsDir || zIsDir; //是否转向

        if (xPos.isEnable)
        {
            if (transform.localPosition.x < xPos.min)
                newPos.x = xPos.min;

            if (transform.localPosition.x > xPos.max)
                newPos.x = xPos.max;
        }

        if (yPos.isEnable)
        {
            if (transform.localPosition.y < yPos.min)
                newPos.y = yPos.min;

            if (transform.localPosition.y > yPos.max)
                newPos.y = yPos.max;
        }

        if (zPos.isEnable)
        {
            if (transform.localPosition.z < zPos.min)
                newPos.z = zPos.min;

            if (transform.localPosition.z > zPos.max)
                newPos.z = zPos.max;
        }

        //超出范围
        if (isDiversion)
        {
            //设置位置不能超出范围
            transform.localPosition = newPos;
            RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
        }

    }
    #endregion


}

设置成基类(为方便不同物体的操作方法重写)

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

/// <summary>
/// 范围位置
/// </summary>
[Serializable]
public class RestrictedDirection2
{
    public bool isEnable = true; //true启用 false禁用
    public float min;
    public float max;
}
/// <summary>
/// 随机移动效果
/// </summary>
public class BaseRandomMove : MonoBehaviour
{
    protected Vector3 originalPos; //文字原位置

    [SerializeField] protected float speed = 3; //速度

    [Header("指针方向")]
    [SerializeField] protected Transform pole; //标杆(负责旋转)
    [SerializeField] protected Transform pointDis; //点位方向(物体移动方向)注意:点的位置要超出墙的包裹范围

    [Header("范围限制距离(LocalPosition)")]
    [SerializeField] protected RestrictedDirection2 xPos;
    [SerializeField] protected RestrictedDirection2 yPos;
    [SerializeField] protected RestrictedDirection2 zPos;

    void Start()
    {
        //InitData(); //初始化数据

    }

    void Update()
    {
        //MoveCheckScope(); //物体移动并检测范围
        按下测试
        //if (Input.GetKeyDown(KeyCode.A))
        //{
        //    RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
        //}
    }

    #region 初始化数据
    public virtual void InitData()
    {
       
        //标杆和点位获取
        if (pole == null)
            pole = transform.Find("pole");
        if (pointDis == null)
            pointDis = pole.Find("pointDis");

        //默认隐藏标杆
        pole.gameObject.SetActive(false);

        originalPos = transform.position; //记录原点位置
        RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
    }
    #endregion

    #region 物体移动和范围检测
    protected virtual void MoveCheckScope()
    {
        //绘制线条
        Debug.DrawLine(transform.position, pointDis.position, Color.red);
        transform.position = Vector3.MoveTowards(transform.position, pointDis.position, speed * Time.deltaTime);

        CheckScope();//检测是否碰到墙壁

    }
    #endregion

    #region 随机转向
    /// <summary>
    /// 随机方向
    /// </summary>
    /// <param name="min">最小值</param>
    /// <param name="max">最大值</param>
    /// <param name="max">旋转轴设置 不旋转 Vector3(0,0,0),所有轴旋转Vector3(1,1,1)</param>
    protected virtual void RandomDirection(float min, float max, Vector3 normalAngle)
    {
        normalAngle = new Vector3(Mathf.Clamp(normalAngle.x, 0, 1), Mathf.Clamp(normalAngle.y, 0, 1), Mathf.Clamp(normalAngle.z, 0, 1)); //旋转轴归一化
        float angle = UnityEngine.Random.Range(min, max);//随机旋转

        pole.localRotation = Quaternion.Euler(normalAngle * angle); //旋转标杆
    }
    #endregion

    #region 检测是否碰到墙壁
    bool isDiversion;//是否转向
    bool xIsDir; //x轴是否超出距离
    bool yIsDir; //y轴是否超出距离
    bool zIsDir; //z轴是否超出距离
    protected virtual void CheckScope()
    {
        isDiversion = false;//是否超出距离
        Vector3 newPos = transform.localPosition;

        //检测轴是否超出距离
        xIsDir = xPos.isEnable && (transform.localPosition.x < xPos.min || transform.localPosition.x > xPos.max);
        yIsDir = yPos.isEnable && (transform.localPosition.y < yPos.min || transform.localPosition.y > yPos.max);
        zIsDir = zPos.isEnable && (transform.localPosition.z < zPos.min || transform.localPosition.z > zPos.max);

        isDiversion = xIsDir || yIsDir || zIsDir; //是否转向

        if (xPos.isEnable)
        {
            if (transform.localPosition.x < xPos.min)
                newPos.x = xPos.min;

            if (transform.localPosition.x > xPos.max)
                newPos.x = xPos.max;
        }

        if (yPos.isEnable)
        {
            if (transform.localPosition.y < yPos.min)
                newPos.y = yPos.min;

            if (transform.localPosition.y > yPos.max)
                newPos.y = yPos.max;
        }

        if (zPos.isEnable)
        {
            if (transform.localPosition.z < zPos.min)
                newPos.z = zPos.min;

            if (transform.localPosition.z > zPos.max)
                newPos.z = zPos.max;
        }

        //超出范围
        if (isDiversion)
        {
            //设置位置不能超出范围
            transform.localPosition = newPos;
            RandomDirection(0, 360, new Vector3(0, 0, 1)); //随机转向
        }

    }
    #endregion


}

三、界面布局

猜你喜欢

转载自blog.csdn.net/qq_42345116/article/details/128643304
今日推荐