unity playercontroller包含什么?

2021-03-29 18:26发布

2条回答
游戏开发狗 -游戏开发爱好者
1楼 · 2021-03-30 13:43.采纳回答

角色控制器包含了相机的跟随、视角的旋转、角色的移动、跳跃等功能,以下是角色控制器的具体代码:

public class PlayerController : MonoBehaviour
{
    public Transform Itself;//自己本身
    public GameObject Cam;//摄像机
    public bool Gravity=true;//重力
    public bool inAir=true;//空中

    //方便移动和跳跃(外面只需要修改这里就可以移动跳跃旋转)
    public bool ForwardMove = false;
    public bool BackMove = false;
    public bool RightMove = false;
    public bool LeftMove = false;
    public bool IsJump = false;
    public Vector2 Rot = Vector2.zero;//旋转值
    public bool IsTouchPadRot = false;
    public float JumpSpeed=15f;//跳跃速度
    public float MoveSpeed=8f;//速度
    public float RotX_Speed=10f;//旋转x速度
    public float RotY_Speed=10f;//旋转y速度
    public Vector3 velocity = Vector3.zero;
    public bool IsRot = true;//是否使用旋转
    public bool IsPC_Rot = true;//旋转采用电脑或者其他设备
    public float CapsuleR=0.5f;//胶囊半径
    public float ShiftAcceleration=1.7f;//加速倍速度

    public Vector3 CapsuleP1=Vector3.zero;//胶囊1负
    public Vector3 CapsuleP2=Vector3.zero;//胶囊2正
    public bool CameraSpace=true;//相机空间
    public Vector3 ForceVelocity=Vector3.zero;//力速度
    public float StepsPerSecond = 50;//步长秒
    public float Acceleration = 50f;//加速
    public bool UseLag = false;//使用滞后
    public float LagTimeLeft;//剩余滞后时间
    public float LagTime = 0.1f;//滞后时间
    public float oldTime=0;//计时
    public static readonly int[] SearchDirVert = { 1, -1, 0, 0, 1, 1, -1, -1 };//搜索方向垂直
    public static readonly int[] SearchDirHor = { 0, 0, 1, -1, -1, 1, 1, -1 };//搜索方向水平

    private void Update()
    {
        if (Cam == null) Cam = Camera.main.transform.gameObject;
        //自身
        if (Itself == null) Itself = transform;
        //胶囊参数
        CapsuleCollider capsuleCollider = Itself.GetComponent();
        if (capsuleCollider != null)
        {
            CapsuleP1 = capsuleCollider.center + Vector3.up * (capsuleCollider.height / 2 - capsuleCollider.radius);
            CapsuleP2 = capsuleCollider.center - Vector3.up * (capsuleCollider.height / 2 - capsuleCollider.radius);
            CapsuleR = capsuleCollider.radius;
        }
        
        //模仿滞后
        LagTimeLeft -= Time.deltaTime;
        if (UseLag && LagTimeLeft > 0) return;
        LagTimeLeft = LagTime;

        //确定观看方向
        Vector3 lookDir;
        if (CameraSpace)
        {
            lookDir = new Vector3(Cam.transform.forward.x, Cam.transform.forward.y, Cam.transform.forward.z);
            if (Gravity) lookDir.y = 0;
        }
        else lookDir = Itself.transform.forward;

        lookDir = lookDir.normalized;
        Vector3 strafeDir = Vector3.Cross(Vector3.up, lookDir);
        //移动的
        Vector3 direction = new Vector3(0, 0, 0);
        if (Input.GetKeyDown(KeyCode.LeftShift)) { MoveSpeed *= ShiftAcceleration;}
        if ( Input.GetKeyUp(KeyCode.LeftShift)) { MoveSpeed /= ShiftAcceleration;}
        if (IsJump||Input.GetKey(KeyCode.Space) && !inAir) { velocity.y = JumpSpeed;IsJump = false; }
        if (ForwardMove||Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) { direction += lookDir; }
        if (BackMove||Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) { direction -= lookDir; }
        if (RightMove||Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) { direction += strafeDir; }
        if (LeftMove||Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)) { direction -= strafeDir; }
        if (IsRot)
        {
            if (IsPC_Rot)
            {
                Cam.transform.Rotate(new Vector3(-Input.GetAxis("Mouse Y"), 0, 0) * RotY_Speed * Time.deltaTime);
                Itself.Rotate(new Vector3(0, Input.GetAxis("Mouse X"), 0) * Time.deltaTime * RotX_Speed);
            }
            else
            {
                if (IsTouchPadRot)
                {
                     Cam.transform.Rotate(new Vector3(-Rot.y, 0, 0) * RotY_Speed * Time.deltaTime);
                     Itself.Rotate(new Vector3(0, Rot.x, 0) * Time.deltaTime * RotX_Speed);
                    //rot.x += Time.deltaTime * RotX_Speed * Rot.x;
                   // rot.y += Time.deltaTime * RotY_Speed * Rot.y;
                    //Cam.transform.rotation = Quaternion.Euler(-rot.y, 0, 0);
                    //Itself.rotation = Quaternion.Euler(0, rot.x, 0);
                    IsTouchPadRot = false;
                }
            }
        }
        direction *= MoveSpeed * 10;
        float deltaTime = Time.deltaTime; if (UseLag) deltaTime = Time.realtimeSinceStartup - oldTime;
        Itself.position = MovePlayer(Itself.position, direction, deltaTime); //不调试时使用增量时间
        oldTime = Time.realtimeSinceStartup;
    }

    public Vector3 MovePlayer(Vector3 pos, Vector3 direction, float time) //方向是控制器发送电荷的地方,速度是旧的速度
    {
        //计算迭代次数
        int numSteps = (int)(time * StepsPerSecond) + 1;
        float stepTime = time / numSteps;
        if (numSteps > StepsPerSecond / 10f) numSteps = (int)(StepsPerSecond / 10f); //如果fps太低,则断开速度

        for (int i = 0; i < numSteps; i++)
        {
            Vector3 initialPos = pos; //防止卡住
            //调节速度
            if (direction.sqrMagnitude > 0.01f) //如果移动
            {
                velocity += direction.normalized * Acceleration * stepTime;
                velocity = Vector3.ClampMagnitude(velocity, MoveSpeed);
            }
            else
            {
                Vector3 velocityModifier = velocity.normalized * Acceleration * stepTime;
                if (velocity.sqrMagnitude > velocityModifier.sqrMagnitude) velocity -= velocityModifier; //如果还在移动
                else velocity = Vector3.zero;
            }
            pos = TryMove(pos, velocity * stepTime);
            //应用重力
            if (Gravity)
            {
                ForceVelocity += Vector3.down * stepTime * 9.8f; //加速下降
                if (ForceVelocity.y * stepTime > CapsuleR) ForceVelocity.y = CapsuleR / stepTime; //极限速度
                Vector3 fallPos = pos + ForceVelocity * stepTime;
                if (!Physics.CheckSphere(fallPos + CapsuleP2, CapsuleR) && !Physics.CheckSphere(fallPos + CapsuleP1, CapsuleR)) //也许胶囊1是不必要的
                { pos = fallPos; inAir = true; } //如果脚下什么都没有掉下来
                else { ForceVelocity.y = 0; inAir = false; } //如果检测到地面,停止坠落
            }
            //检查卡住
            if (Physics.CheckSphere(pos + CapsuleP1, CapsuleR) || Physics.CheckSphere(pos + CapsuleP2, CapsuleR) || Physics.Linecast(initialPos, pos))
            {
                Debug.Log("Controller stuck(碰撞器卡住)");
                if (Physics.CheckSphere(pos + CapsuleP1, CapsuleR) || Physics.CheckSphere(pos + CapsuleP2, CapsuleR))
                {
                    Debug.Log("CharController locked(碰撞器锁定)");pos = GetOutofStuck(pos);
                }
                pos = initialPos;velocity = new Vector3(0, velocity.y+ 0.1f, 0);
            }
            //else Debug.Log("notstuck");
        }
        return pos;
    }

    public Vector3 TryMove(Vector3 pos, Vector3 moveVector)
    {
        //检查char是否可以直走
        if (!Physics.CheckSphere(pos + moveVector + CapsuleP1, CapsuleR) && !Physics.CheckSphere(pos + moveVector + CapsuleP2, CapsuleR))
        { return pos + moveVector; }

        //准备载体
        Vector3 perpHor = Vector3.Cross(moveVector, Vector3.up).normalized;
        Vector3 perpVert = Vector3.Cross(moveVector, perpHor).normalized;
        float moveDist = moveVector.magnitude;

        //如果char不能直接找到替代位置
        for (float i = 0.5f; i < 100f; i = i * 1.5f + 0.5f)
            for (int dir = 0; dir < 8; dir++)
            {
                Vector3 possibleDir = (moveVector + perpHor * SearchDirHor[dir] * i * moveDist * 0.1f + perpVert * SearchDirVert[dir] * i * moveDist * 0.1f).normalized;
                possibleDir *= Vector3.Dot(moveVector, possibleDir);
                //possibleDir = possibleDir*0.5f + possibleDir.normalized*moveDist * 0.5f;

                if (!Physics.CheckSphere(pos + possibleDir + CapsuleP1, CapsuleR) && !Physics.CheckSphere(pos + possibleDir +CapsuleP2, CapsuleR))
                { return pos + possibleDir; }
            }

        //如果找不到替代位置-返回原始位置
        return pos;
    }

    public Vector3 GetOutofStuck(Vector3 pos)
    {
        for (float dist = 0.07f; dist < 3f; dist *= 1.5f)
            for (int xi = 0; xi < 20; xi++)
                for (int zi = 0; zi < 20; zi++)
                {
                    int x = 0; int z = 0;
                    if (xi % 2 == 0) x = xi * xi; else x = -(xi + 1) * (xi + 1);
                    if (zi % 2 == 0) z = zi * zi; else z = -(zi + 1) * (zi + 1);

                    Vector3 dir = (new Vector3(x, 150, z)).normalized;
                    dir.y -= 0.5f;
                    dir = dir.normalized * dist;

                    if (!Physics.CheckSphere(pos + dir + CapsuleP1, CapsuleR) && !Physics.CheckSphere(pos + dir + CapsuleP2, CapsuleR))
                        return pos + dir;
                }

        return pos;
    }
}


老杜
2楼 · 2021-04-01 15:51

这个模块包含了GameObjects及其相关联的组件、属性、动作、模型、纹理等等,可以实现人物的移动和碰撞

相关问题推荐

  • 回答 6

    第一步:对着Assets点击右键,选择ExportPackage第二步:选择场景文件以及和场景相关的资源或者素材,然后点击Export第三步:给导出的资源取名,并且选择要保存的位置即可

  • 回答 87
    已采纳

    玩游戏玩的很好,说明你对于游戏里面的规则、剧情设置还是比较了解的,对于从事游戏相关岗位来说也是优势之一。但是学习游戏开发还是要对游戏开发的工作内容做进一步的了解,游戏开发涉及代码较多,可以通过进一步的了解,判断自己是否适合学习这个方向,另外...

  • 回答 11

    游戏开发入门不难。后期发展需要你有丰富的奇思妙想。游戏开发肯定是培训好,自学学得不系统,并且不易发现自身薄弱之处。游戏开发的学习时长还是要看你自己对知识与技术的掌握能力,一般来说,游戏开发的学习时长大约在五个月左右。...

  • 回答 18

    个人觉得如果有一定的技术基础的话还是可以考虑自学,如果零基础的话可能会有些难度

  • 回答 10

    问题还是出在粒子的sorting fudge。在unity的2d模式下,游戏本身的背景相当于是sorting fudge的0,当你把粒子的sorting fudge设为0以上的时候,粒子就都会被背景盖住。所以在3d模式下给alpha正值来给add垫底的话,到了2d模式下就会通通不显示。所以遇上这样的...

  • 回答 17

    虚幻4引擎,你会看到和平精英加载页面左下角有这个图标。

  • 回答 8
    已采纳

    转载知乎上的两位答友的回答,各有道理。作者:风小锐链接:https://www.zhihu.com/question/322249959/answer/675883379来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。未来Unity有可能出现3A大作吗? 有可能。基于Unity已...

  • 回答 11

    在Assets文件夹里面.点击右键Create/Material即可以创建材质球

  • 回答 23

    可以让模型师直接作出这样的形状,如果用纯Unity制作,就要用基本游戏对象拼接了,包括楼梯,城堡,都可以拼接出来。正常情况不会这样做,因为不够精美,都是建模师来实现,毕竟Unity不属于专业的建模软件,侧重于实现功能。...

  • 回答 18

    粒子系统由粒子发射器、粒子动画器和粒子渲染器三部分组成,主要用于游戏场景中一些特殊效果,如水、烟火等等

  • 回答 18

    首先,Python开发游戏非常尴尬,原因是没有好用的游戏开发库。Python开发游戏仅推荐PyGame,PyGame是对多年以前很流行的游戏开发库——SDL的封装。但是说实话功能太简陋了,做个动画都得考虑刷新的问题。楼主要做简单小游戏,只需要画一两周熟悉Unity引擎,然...

  • 回答 9

    1.标记水体碰撞的位置2.计算水波的传递 通过波动公式,3D或者2D 波动公式都行3.水面顶点采样波动传递结果计算结果做顶点Y轴偏移

  • 回答 15

    Unity3D中两种阴影的实现传统的ShadowMapShadowMap说起来十分简单,把摄像机和光源的位置重叠,那么场景中该光源的阴影区域就是那些摄像机看不到的地方,主要应用在前向渲染路径中。具体实现分以下几个步骤:如果有平行光开启了阴影,Unity就会为该光源计算它...

  • 回答 18

    Doozy UI是Unity UI视图层的框架,本身使用的还是UGUI的组件,但提供了一套强大的UI管理功能,可以很方便的实现一些炫酷效果,方便的UI系统管理与事件传递机制。

  • 回答 12

    Unity3d更好,因为U3D占有的市场更大,目前cocos大都是用来开发棋牌游戏的,在这方面它有着巨大的优势。而Unity3d既可以用来开发大型3D游戏,也可以用来开发vr游戏、vr应用,这是比较不错的,未来有着巨大的前景。另外ue4也是个不错的选择,近年来用ue4开发的...

  • 回答 11

    当Unity 需要做热更新的时候(2013年开始),而普通的C#又做不到的时候,而对于游戏行业来说Lua脚本热更新已经是很成熟的方案,自然Lua 热更新就成为了Unity热更新的首选。

没有解决我的问题,去提问