分类:Unity3D

Unity 默认Inspector支持的一些属性

[HideInInspector]:使用了该属性的变量不显示在inspector 但是被序列化。即不会显示,也不会被外部类调用。

[SerializeField]:将不会被序列化的非公共变量可以序列化,这么在下次读取时,就是上次赋值的值。

[ExecuteInEditMode()]:这个函数可以使代码在编辑模式下运行,不需要运行游戏;

[ExecuteInEditMode]: 编辑环境中该功能(类)生效,简单讲就是。不运行游戏。就可你让你的功能起作用,比如:NGUI中的Slider

[MenuItem(“”)]:导航条中加入自定义菜单。

[CustomEditor(typeof(EButton))]:绑定使用该类。必须依赖EButton类。

[RequireComponent (typeof (ClassName))]:添加该类时。自动会加入ClassName类。

[ContextMenu (“XXX”)]:加入Inspector面板右键菜单。点击执行该功能。

[AddComponentMenu(“XXX/XX/XXX”)]:菜单中出现定义的该类。

Unity3d 实现移动端的触摸屏操作-场景的缩放移动

通过Input.touchCount来判断触控点位,通过Input.GetTouch(0).phase来判断移动的类型。

其中phase(状态)有以下这几种:
Began:手指刚刚触摸屏幕
Moved:手指在屏幕上移动
Stationary:手指触摸屏幕,但自最后一阵没有移动
Ended:手指离开屏幕
Canceled:系统取消触控跟踪,原因如把设备放在脸上或同时超过5个触摸点

代码中主要用到的是TouchPhase.Began和TouchPhase.Moved。
完整代码如下,放置到主摄像机上即可:

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

public class MobileTouch : MonoBehaviour
{
    //是否缩放
    private bool IsZoom = false;
    //当前双指触控间距
    private float DoubleTouchCurrDis;
    //过去双指触控间距
    private float DoubleTouchLastDis;

    //记录手指触碰的位置
    Vector2 m_screenPos = new Vector2();

    void Start()
    {

    }

    void Update()
    {
        if ((Input.touchCount > 1) && (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved))
        {
            // 多点触控
            Touch touch1 = Input.GetTouch(0);
            Touch touch2 = Input.GetTouch(1);

            DoubleTouchCurrDis = Vector2.Distance(touch1.position, touch2.position);

            if (!IsZoom)
            {
                DoubleTouchLastDis = DoubleTouchCurrDis;
                IsZoom = true;
            }

            float distance = DoubleTouchCurrDis - DoubleTouchLastDis;
            Camera.main.fieldOfView += (distance > 0 ? -1 : 1) * 1;//更改了摄像头的高度
            DoubleTouchLastDis = DoubleTouchCurrDis;
        }
        else if (Input.touchCount == 1)
        {
            // 单点移动
            if (Input.touches[0].phase == TouchPhase.Began)
            {
                //记录手指刚触碰的位置
                m_screenPos = Input.touches[0].position;
            }
            if (Input.touches[0].phase == TouchPhase.Moved) //手指在屏幕上移动,移动摄像机
            {
                transform.Translate(new Vector3(Input.touches[0].deltaPosition.x * Time.deltaTime * -1, Input.touches[0].deltaPosition.y * Time.deltaTime * -1, 0));
            }
        }
    }
}

转:Unity相机跟随多种实现方式

转自:https://blog.csdn.net/qq_37310110/article/details/94007394

一:设置目标物为相机的父节点
描述:最简单,最基础,效果最不理想,锁死跟随视角

二:常规设置固定相对向量偏移
描述:推荐指数***,代码实现简,效果比较生硬

 public Transform target;
    private Vector3 offset;
    void Start()
    {
        //设置相对偏移
        offset = target.position - this.transform.position;
    }
    void Update()
    {
        //更新位置
        this.transform.position = target.position - offset;
    }

三:添加旋转角度
描述:推荐指数***,在二的基础上添加距离差值和旋转角度差值,效果流畅

   private Vector3 offset;//相机相对于玩家的位置
    public Transform target;
    private Vector3 pos;
    public float speed = 2;
    private void Start()
    {
        offset =  transform.position - target.position;
    }
    // Update is called once per frame
    void Update()
    {
        pos = target.position + offset;
        this.transform.position = Vector3.Lerp(transform.position, pos, speed * Time.deltaTime);//调整相机与玩家之间的距离

        Quaternion angel = Quaternion.LookRotation(target.position - transform.position);//获取旋转角度
        transform.rotation = Quaternion.Slerp(transform.rotation, angel, speed * Time.deltaTime);
    }
 

四: 第三背后视角
描述:推荐指数*****,流畅参数可调。对相机的位置实时计算

 public Transform target;
    public float distanceUp = 10f;//相机与目标的竖直高度参数
    public float distanceAway = 10f;//相机与目标的水平距离参数
    public float smooth = 2f;//位置平滑移动插值参数值
    public float camDepthSmooth = 20f;

    void Update()
    {
        // 鼠标轴控制相机的远近
        if ((Input.mouseScrollDelta.y < 0 && Camera.main.fieldOfView >= 3) || Input.mouseScrollDelta.y > 0 && Camera.main.fieldOfView <= 80)
        {
            Camera.main.fieldOfView += Input.mouseScrollDelta.y * camDepthSmooth * Time.deltaTime;
        }
    }

    void LateUpdate()
    {
        //计算出相机的位置
        Vector3 disPos = target.position + Vector3.up * distanceUp - target.forward * distanceAway;

        transform.position = Vector3.Lerp(transform.position, disPos, Time.deltaTime * smooth);
        //相机的角度
        transform.LookAt(target.position);
    }

五:自由 视角

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class target_control : MonoBehaviour {

    public Transform _target;
    public float distance = 50.0f;
    public float xSpeed = 250.0f;
    public float ySpeed = 120.0f;

    public int yMinLimit = -20;
    public int yMaxLimit = 80;

    private bool orbit = false;
    private bool pan = false;
    private bool zoom = false;
    private float zoomValue = 0;

    public float orbitDampX = 0.0f;
    public float orbitDampY = 0.0f;
    float panDampX = 0.0f;
    float panDampY = 0.0f;
    public float zoomDamp = 0.0f;
    public float dampingTime = 0.0f;

    public float x = 180.0f;
    public float y = 0.0f;

    public int planFactor = 5;
    public float zoomFactor = 2.0f;
    public Vector2 distLimit;

    public static Quaternion _rotation;
    public static Vector3 _position;
    public static target_control _target_control;
    public float _z_distance;
    private Vector3 angles;

    private Vector2 oldPosition1;   
    private Vector2 oldPosition2;

    public float _target_distance = 5;

    private float target_x;
    private float target_y;
    private Vector3 _target_pos = Vector3.zero;

    public bool change_distance() 
    {
        distance = Mathf.Lerp(distance, _target_distance, 0.04f);
        Debug.Log(distance + "/" + _target_distance);
        updateCamera();
        if (Mathf.Abs(distance - _target_distance) < 0.01f)
            return false;
        return true;
    }
    public bool change_distance(float _dis)
    {
        distance = Mathf.Lerp(distance, _dis, 0.004f);

        updateCamera();
        if (Mathf.Abs(distance - _dis) < 0.01f)
            return false;
        return true;
    }

    void Start()
    {
        _target_distance = distance;
        _z_distance = distance;
        angles = transform.eulerAngles;
        x = angles.y;
        y = angles.x;

        // Make the rigid body not change rotation
        if (GetComponent<Rigidbody>())
            GetComponent<Rigidbody>().freezeRotation = true;
    }
    // Update is called once per frame
    void LateUpdate () {

        if (EventSystem.current.IsPointerOverGameObject()||_target ==null)
        {
            return;
        }

        if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
            if (Input.touchCount == 1)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Moved)
                {
                    orbit = true;
                }
                else
                {
                    orbit = false;
                }
            }
            else
            {
                orbit = false;
            }

            if (Input.touchCount > 1)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved)
                {
                    var tempPosition1 = Input.GetTouch(0).position;
                    var tempPosition2 = Input.GetTouch(1).position;
                    if (isEnlarge(oldPosition1, oldPosition2, tempPosition1, tempPosition2))
                    {
                        zoomValue = 0.1f;
                        zoom = true;
                    }
                    else
                    {
                        zoomValue = -0.1f;
                        zoom = true;
                    }
                    oldPosition1 = tempPosition1;
                    oldPosition2 = tempPosition2;
                }
                else
                {
                    zoom = false;
                }
            }
            else
            {
                zoom = false;
            }
        } 
       else if (Application.platform == RuntimePlatform.Android)
        {

            if (Input.touchCount == 1)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Moved)
                {
                    orbit = true;
                }
                else
                {
                    orbit = false;
                }
            }
            else
            {
                orbit = false;
            }

            if (Input.touchCount > 1)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved)
                {
                    var tempPosition1 = Input.GetTouch(0).position;
                    var tempPosition2 = Input.GetTouch(1).position;
                    if (isEnlarge(oldPosition1, oldPosition2, tempPosition1, tempPosition2))
                    {
                        zoomValue = 0.1f;
                        zoom = true;
                    }
                    else
                    {
                        zoomValue = -0.1f;
                        zoom = true;
                    }
                    oldPosition1 = tempPosition1;
                    oldPosition2 = tempPosition2;
                }
                else
                {
                    zoom = false;
                }
            }
            else
            {
                zoom = false;
            }
        }
        else
        {
            if (Input.GetMouseButton(1))
            {
                orbit = true;
            }
            else
            {
                orbit = false;
            }

            if (Input.GetAxisRaw("Mouse ScrollWheel") != null)
            {
                zoomValue = Input.GetAxisRaw("Mouse ScrollWheel");
                zoom = true;
            }
            else
            {
                zoom = false;
            }
        }

        if (orbit)
        {

            orbitDampX = Mathf.Lerp(orbitDampX, Input.GetAxis("Mouse X"), dampingTime * Time.deltaTime);
            orbitDampY = Mathf.Lerp(orbitDampY, Input.GetAxis("Mouse Y"), dampingTime * Time.deltaTime);
        }
        else
        {
            orbitDampX = Mathf.Lerp(orbitDampX, 0, dampingTime * Time.deltaTime);
            orbitDampY = Mathf.Lerp(orbitDampY, 0, dampingTime * Time.deltaTime);
        }

        if (zoom)
        {
            zoomDamp = Mathf.Lerp(zoomDamp, zoomValue, dampingTime * Time.deltaTime);
        }
        else
        {
            zoomDamp = Mathf.Lerp(zoomDamp, 0, dampingTime * Time.deltaTime);
        }

        if (!checkLerp(orbitDampX, 0) || !checkLerp(orbitDampY, 0))
        {
            doOrbit();
        }
        if (!checkLerp(zoomDamp, 0))
        {
            doZoom();
        }

    }

    bool isEnlarge(Vector2 oP1,Vector2 oP2 , Vector2 nP1, Vector2 nP2 )  
    {   
        var leng1 =Mathf.Sqrt((oP1.x-oP2.x)*(oP1.x-oP2.x)+(oP1.y-oP2.y)*(oP1.y-oP2.y));   
        var leng2 =Mathf.Sqrt((nP1.x-nP2.x)*(nP1.x-nP2.x)+(nP1.y-nP2.y)*(nP1.y-nP2.y));   
        if(leng1<leng2)   
        {   
            //big
             return true;    
        }else   
        {   
            //small
            return false;    
        }   
    }

    bool checkLerp(float a,float b)
    {
        if (Mathf.Approximately(a, b))
        {
            return true;
        }
        return false;
    }
    void doOrbit()
    {
        if (_target) 
         {          
             x += orbitDampX * xSpeed * 0.02f;
             y -= orbitDampY * ySpeed * 0.02f;

            y = ClampAngle(y, yMinLimit, yMaxLimit);
            updateCamera();
        }
    }
    void doZoom()
    {
        distance -= zoomDamp * zoomFactor;
        distance = Mathf.Clamp(distance, -distLimit.x, distLimit.y);
        updateCamera();
    }

    void updateCamera()
    {
        var rotation = Quaternion.Euler(y, x, 0);
        var position = rotation * new Vector3(0.0f, 0.0f, -distance) + _target.position;

        transform.rotation = rotation;
        transform.position = position;
    }

    static float ClampAngle (float angle,float min,float max)
    {
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;
        return Mathf.Clamp(angle, min, max);
    }
}

关于 “SetDestination can only be called on an active agent that has been placed on a NavMesh” 真正的解决方案

最近碰到了 "SetDestination can only be called on an active agent that has been placed on a NavMesh" 的问题,关键点不在于不会用Navmesh,而是真的他就这么报错了。

找了很多办法,耗时1天,终于在国外论坛上看到真正的解决方案了。

常规解决方案:

  1. 检查场景是否烘焙。
  2. 检查目标或自己是否位于navmesh上,不是在半空。
  3. 尝试使用NavMesh.SamplePosition方法。
    GameObject go = new GameObject("Target");
    Vector3 sourcePostion = new Vector3( 100, 20, 100 );//The position you want to place your agent
    NavMeshHit closestHit;
    if( NavMesh.SamplePosition(  sourcePostion, out closestHit, 500, 1 ) ){
      go.transform.position = closestHit.position;
      go.AddComponent<NavMeshAgent>();
      //TODO
    }
    else{
      Debug.Log("...");
    }

如果常规方法没解决,且寻路是时好时坏,对象和自己均是代码生成的,那八九不离十肯定碰到了我碰到的问题。
解决方法很简单:
在prefab里就添加了NavMeshAgent组件的,把他勾掉,然后在物体的start里面agent.enabled = true;
如果是在awake代码生成的,AddComponent后把enabled设置成false,然后在物体的start里面agent.enabled = true;

示例:

void Awake () {
    // 添加寻路组件
    agent = this.gameObject.AddComponent<NavMeshAgent> ();
    agent.speed = 3.5f;
    agent.enabled = false;
    // ...
}

// Use this for initialization
void Start () {
    agent.enabled = true;
}

Updating Homebrew… 一直卡住怎么处理?

brew install安装一个东西,然后突然 Updating Homebrew... 卡住了,之前一直公司网好像不卡,现在疫情在自己家,它居然能卡着完全不动。。。

那我就把它换个源吧~ ,换成 aliyun 的源。

替换 / 还原 brew.git 仓库地址

替换成阿里巴巴的 brew.git 仓库地址:
cd "$(brew --repo)"
git remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git

=======================================================
还原为官方提供的 brew.git 仓库地址
cd "$(brew --repo)"
git remote set-url origin https://github.com/Homebrew/brew.git

替换 / 还原 homebrew-core.git 仓库地址

替换成阿里巴巴的 homebrew-core.git 仓库地址:
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://mirrors.aliyun.com/homebrew/homebrew-core.git

=======================================================
还原为官方提供的 homebrew-core.git 仓库地址
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://github.com/Homebrew/homebrew-core.git

替换 / 还原 homebrew-bottles 访问地址

这个步骤跟你的 macOS 系统使用的 shell 版本有关系

所以,先来查看当前使用的 shell 版本

echo $SHELL

  • 如果你的输出结果是 /bin/zsh,参考?的 zsh 终端操作方式
  • 如果你的输出结果是 /bin/bash,参考?的 bash 终端操作方式

zsh 终端操作方式

替换成阿里巴巴的 homebrew-bottles 访问地址:
echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.aliyun.com/homebrew/homebrew-bottles' >> ~/.zshrc
source ~/.zshrc

=======================================================

还原为官方提供的 homebrew-bottles 访问地址

vi ~/.zshrc

然后,删除 HOMEBREW_BOTTLE_DOMAIN 这一行配置

source ~/.zshrc

bash 终端操作方式

替换 homebrew-bottles 访问 URL:

echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.aliyun.com/homebrew/homebrew-bottles' >> ~/.bash_profile
source ~/.bash_profile

=======================================================

还原为官方提供的 homebrew-bottles 访问地址

vi ~/.bash_profile

然后,删除 HOMEBREW_BOTTLE_DOMAIN 这一行配置

source ~/.bash_profile