• Unity 游戏开发、03 基础篇 | C#初级编程


    C#初级编程

    https://learn.u3d.cn/tutorial/beginner-gameplay-scripting

    8 Update 和 FixedUpdate

    Update(不是按固定时间调用的) 经常用于

    • 移动非物理特性的物体(不是物理对象)
    • 简单定时器
    • 接收输入

    FixedUpdate(调用时间间隔相同)

    • 进行任何必要的物理计算(任何物理对象)
      • 最好使用力来定义移动

    使用 IDE 的 Unity Event Functions 插入函数


    9 点积、叉积

    点积算出标量如果点积为 0 则两个向量互相垂直,飞机模拟例子:

    • 点积 = 0,飞机前向 Z 轴 与 Y 轴垂直,此时阻力最小
    • 点积 > 0,飞机在爬升,此时阻力变大
    • 点积 < 0,飞机在俯冲

    叉积算出新向量。使用左手坐标系根据 A 、B 确定 C 的方向(中指)

    • 为了确定围绕哪个轴施加扭矩 来转动坦克炮塔
    • 如果知道炮塔目前朝向目标朝向,则可以用叉积算出需要围绕的轴的方向

    10 启用和禁用组件

    private Light myLight;
    
    private void Start()
    {
        myLight = GetComponent();
    }
    
    private void Update()
    {
        if (Input.GetKeyUp(KeyCode.Space))
            myLight.enabled = !myLight.enabled;
    }
    

    11 激活游戏对象

    • 父节点无效后,子节点也会一同跟着无效,(不活跃节点在层次结构中依旧可见)
      • 利用父节点保持对对象群的控制
      • 子节点由于父节点被禁用而禁用时,只针对子节点setActive不管用,想要重新激活子节点就必须重新激活父节点
    • 要确认某个节点是否为活跃状态
      • activeSelf 看节点本身
      • activeInHierarchy 看父子关系(父节点关则false;根节点自身为父节点)
    Debug.Log(myObject.activeSelf);
    Debug.Log(myObject.activeInHierarchy);
    

    12 物体移动

    • 默认移动,旋转都是 Space.self
    • 移动一个有碰撞体的对象(带物理效果的物体),不能用 Translate 与 Rotate
    public void Rotate(Vector3 axis, float angle) => this.Rotate(axis, angle, Space.Self);
    

    13 LookAt

    让摄像机看向某一物体

    public Transform target;
    private void Update()
    {
        transform.LookAt(target);
    }
    

    14 Lerp

    线性插值会在两个给定值之间找到某个百分比的值。

    float result = Mathf.Lerp (3f, 5f, 0.5f);
    // Color.Lerp 和 Vector3.Lerp
    
    Vector3 from = new Vector3 (1f, 2f, 3f);
    Vector3 to = new Vector3 (5f, 6f, 7f);
    // 此处 result = (4, 5, 6)
    Vector3 result = Vector3.Lerp (from, to, 0.75f);
    

    在对值进行平滑时,通常情况下最好使用 SmoothDamp 函数。想要实现特定效果时,才应使用 Lerp 进行平滑。

    Unity - Scripting API: Mathf.SmoothDamp (unity3d.com)

    Need help understanding the Mathf.SmoothDamp function - Unity Forum

    ref velocity 存在的必要性

    如果目标距离较远,函数会尝试加速你的位置,如果目标越来越近,则会减速。为了加速/减速,你需要知道你的速度有多快,这就是速度参数


    16 GetButton、GetKey

    • GetKey 需要使用 KeyCode 类型参数
    • KeyCode 只与特定键相关,建议使用 GetButton
      • 参数是字符串,可以在 Project Settings | Input Manager 中设置,灵活性很大
    • 两种方式都有三种状态:Down、状态、Up
    private void Update()
    {
        if(Input.GetButtonDown("Jump"))
            Debug.Log("按下了空格键");
        if(Input.GetButtonDown("Fire1"))
            Debug.Log("按下了鼠标左键");
    }
    

    17 GetAxis、GetAxisRaw

    • GetButton、GetKey 只返回布尔值
    • GetAxis 返回浮点值,介于-1到1之间
    • GetAxisRaw  返回浮点值,仅返回 -1,0,1,不受平滑过滤参数影响
      • 针对需要严格控制输入的2D游戏非常有用
    • Gravity 按钮松开后归零的速度(越高归零越快)
    • Sensitivity 按钮按下后到达1或-1的速度有多快(越高越快)
    • Dead 值针对手柄盲区(LS、RS轻微转动不影响)(越大盲区越大)
    private void Update()
    {
        float x = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        float x2 = Input.GetAxisRaw("Horizontal");
        float v2 = Input.GetAxisRaw("Vertical");
        Debug.Log($"{x} {v} {x2} {v2}");
    }
    

    void Movement ()
    {
        float forwardMovement = Input.GetAxis("Vertical") * speed * Time.deltaTime;
        float turnMovement = Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime;
    
        transform.Translate(Vector3.forward * forwardMovement);
        transform.Rotate(Vector3.up * turnMovement);
    }
    

    18 OnMouseDown

    用于检测对 带碰撞体组件的物体节点GUI元素 鼠标点击事件

    以下代码针对一个物理物体,每次鼠标点击给予 forward 反方向的推力

    private void OnMouseDown()
    {
        Debug.Log($"点击 {gameObject.name}");
        rb.AddForce(-transform.forward * 500f);
    }
    

    19 GetComponent

    GetComponent 性能消耗大,应该尽量减少调用,最好是在 Awake,Start 调用


    20 deltaTime

    定时器功能与平滑移动(按速度移动)

    public float speed = 8f; 
    public float countdown = 3.0f;
    
    void Update ()
    {
        countdown -= Time.deltaTime;
        if(countdown <= 0.0f)
            light.enabled = true;
    
         if(Input.GetKey(KeyCode.RightArrow))
            transform.position += new Vector3(speed * Time.deltaTime, 0.0f, 0.0f);
    }   
    

    21 值、引用

    • 值类型对应的值被改变,只会影响特定变量
    • 引用类型指向的值被改变,所有包含相同存储地址的引用类型变量都会受到影响
        void Start () 
        {
            //值类型变量
            Vector3 pos = transform.position;  // 值拷贝
            pos = new Vector3(0, 2, 0); 
            
            //引用类型变量
            Transform tran = transform;
            tran.position = new Vector3(0, 2, 0);
        }
    

    22 类

    • 拆分类的功能,不要全部写在一起(单一职责原则)
      • 如射击类、移动类、库存类
    • 多用代码段,比如 ctor 生成构造函数
    • 先全面仔细设计脚本结构,再开始编写一个大类,将各种不同内容囊括其中

    23 Instantiate

    Instantiate 用于动态生成预制体对象(创建预制件的克隆体)

    动态实例化生成的子弹预制体节点被强制转型成了 RigidBody

    public Rigidbody bulletPrefab; // 可以不是GameObject而是绑定的组件
    public Transform firePosition;
    public float bulletSpeed;   
    ...
    Rigidbody bulletInstance = Instantiate(bulletPrefab, firePosition.position, firePosition.rotation) as Rigidbody;
    

    案例中用到了 as 关键字。《C# 8.0本质论》里没有写

    • 按(Rigidbody)显式转换方式如果转换不成功会抛出异常
    • as 运算符类似于强制转换操作;但是,如果转换不可行,as 会返回 null 而不是引发异常

    24 数组

    使用 FindGameObjectsWithTag 初始化查找所有 Tag 为 Player 的节点存储至数组中

    C# 数组是从抽象的基类型Array派生的引用类型

    public GameObject[] players;
    
    void Start()
    {
        players = GameObject.FindGameObjectsWithTag("Player");
        foreach (var player in players)   
        {
            Debug.Log($"{player.name}");
        }
    }
    

    25 Invoke

    • Invoke 调用的函数必须 不包含参数,且无返回值

    其他内容以前笔记有写,略过


    26 enum

    用整数描述方向不易读,可以建立 enum 类型(类内类外都可创建

    enum Direction : short
    {
        North, // 0 
        East,  // 1
        South = 100, // 100
        West   // 101
    };
    void Start()
    {
        Direction myDirection;
        myDirection = Direction.North;
        var newDirection = ReverseDirection(myDirection);
    }
    
    Direction ReverseDirection (Direction dir)
    {
        if(dir == Direction.North)
            dir = Direction.South;
        else if(dir == Direction.South)
            dir = Direction.North;
        else if(dir == Direction.East)
            dir = Direction.West;
        else if(dir == Direction.West)
            dir = Direction.East;
    
        return dir;     
    }
    

    27 switch

    跟 C++ 差不多

    public int intelligence = 5;
    void Start()
    {
        switch (intelligence)
        {
            case 1:
                break;
            case 2:
                break;
            default:
                break;
        }
    }
    

    __EOF__

  • 本文作者: 小能喵喵喵
  • 本文链接: https://www.cnblogs.com/linxiaoxu/p/17703722.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    list容器 常用 API操作
    Java-GUI编程之处理位图
    uniapp 微信小程序根据后端返回的文件链接打开并保存到手机文件夹中【支持doc、docx、txt、xlsx等类型的文件】
    【进阶C语言】数组笔试题解析
    YOLOv7改进:全网原创首发 | 多尺度空洞注意力(MSDA) | 中科院一区顶刊 DilateFormer 2023.9
    微服务(五)——服务注册与发现:Zookeeper&Consul
    Android - Context
    React antd Select 无法在disabled状态下选择并复制输入框内的内容情况分析及解决方案
    统信UOS Linux操作系统下怎么删除某个程序在开始菜单或桌面的快捷方式
    k8s驱逐篇(2)-kubelet节点压力驱逐
  • 原文地址:https://www.cnblogs.com/linxiaoxu/p/17703722.html