游戏开发者使用code buddy能做成什么样? C# Unity

腾讯的Code Buddy

官网介绍: 点此处跳转

其实,腾讯的code buddy (下文简称为buddy) 和现在大多数的AI辅助编程一样,都是帮助各位IT行业的小伙伴更加高效的编辑代码(make your life better ),目前是免费的阶段(个人版免费 企业版与专业版收费详见官网).使用方法与cursor类似.在代码编辑器扩展中安装,然后登陆账号.即可开始使用.使用是很简单的,但是如何去用,也是一门学问.

新的改变

其实现在有一部分的人,还比较抗拒AI辅助编程,认为机器怎么能代替人类呢?不瞒大家,之前的我也是这么人为的,因为之前我接触过AI智能体.unity官方提供的.我现在仍然记忆深刻.当时我确实是用了很少量的代码.写了大概让智能体怎么躲避障碍,怎么追击玩家.然后就是长达10个小时的训练.当时这个训练方式叫:强化学习.如果我稍有改动,比如哪个地方没有想到,哪个地方还可以优化,那么需要重新开始训练.当时我得出的结论就是节省了编码时间,但是时间都用在试错训练上了.于是后来我没有继续再深入的研究AI 智能体.我自我感觉这种办法做游戏AI还是有些浅显.

  1. 为什么要拥抱AI? ,AI目前来说是个大趋势,孙子兵法也提到,我们需要顺势而为,现在的AI工具也多.选择一个适合自己的AI工具,与自己的AI工具磨合成为现在必须行动的一部分;我想讲一个故事来说明为什么现在会使用AI刻不容缓.中学的时候,大家一定学过瓦特的蒸汽机的改良后推动了工业革命,这项伟大的改良直接导致了大量纺织工人的大量失业.但是注意它的用词,是大量 那么为什么不是全部呢?以前我觉得是还有落后的生产厂家在排斥,但是不久之前我想明白了,因为 少量 的纺织工人学会了如何操作蒸汽机 当然,这个可能不是现实,是我自己猜测的.我希望通过这个"故事"使你明白.AI以后会进入我们的生活.而且以后会发展的更加强大.不会使用AI的人,也许会被淘汰.
  2. 辅助编程是什么?,其实我理解的恶辅助编程并不是像现在像buddy 这样你敲个关键字然后等待它给你推荐合适的方法体这样的,其实编辑器自带的智能提示也是辅助编程.只不过buddy这一类的辅助编程做的更智能,更全面.也更方便.
  3. 如何启用buddy? 我使用的是vscode编辑器 , vscode安装插件还是很方便的,直接在插件市场中搜索"腾讯云代码助手 CodeBuddy";截至写稿日期,还不到半个月,已经有11w的装机量.这个成绩还是不错的.
    在这里插入图片描述
    将它下载到vscode还是需要一个小步骤才能正常使用:在vscode的右下角找到buddy的图表,点击它选择启用代码补全:

在这里插入图片描述
如果你够细心的话,你会发现我也启用了GitHub的Copilot,并且我的Copilot是付费版.为了不让Copilot影响buddy的使用结果,还需要将Copilot进行关闭,那么该怎么关闭Copilot呢?
只需要在右下角的Copilot图标处点击,关闭所有选项即可,最后的最后,需要你使用微信号登录,当然你使用其他方式登录也可以.点击右下角的图标,或者是左侧的插件图标都可以
在这里插入图片描述

关闭Copilot
操作完毕之后Copilot那会有个斜杠,那么就代表它的功能已经被屏蔽了.我的vscode中没有继续安装其他的辅助编程,那么剩下所有的智能提示,都是编辑器自带,或者是buddy提供的.

buddy主要功能快捷键

进行代码解释:Shift +Alt + X
进行代码修复:Shift +Alt + Y
进行代码注释:Shift +Alt + M
生成测试单元:Shift +Alt + T
询问 AI 问题:Ctrl +Windows + I
在代码区域打开技术对话:Ctrl +Windows + N

PS:还有在开发中用到的快捷键下方具体开发使用的过程中再介绍

那么到目前为止.buddy 的配置工作已经结束,已经可以在项目中去使用了.为了体现buddy的辅助效果.之前我已经关闭了github的Copilot辅助编程, 目前这算是第一个阶段,新建一个unity工程,并通过注释联想.需求直连(AI对话并让它生成代码)虽然我知道buddy给出的代码应该会有一些问题.我仅仅会修改它的不合理处,不会去人为的写一个代码让它在此基础上继续生成.这个会在第二阶段做个测试,在一个完整的项目中让它生成合理的代码或者直接询问buddy的建议.

那么在这个新建的unity工程中,我准备从level1 开始,就是简单的控制控件.位移,等等基础功能.当然了.工程中的新建脚本,控件添加还是要人工去做的.

首先这个是我新建的工程 ,工程中我已经新建好了一个名为PlayerCtrl.cs的脚本文件.那么通过名字可以知道这个是用来控制游戏物体的移动的.

在这里插入图片描述
那么.打开脚本:开始试试buddy到底如何,再次确认GitHub的Copilot是关闭状态.

默认的脚本如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCtrl : MonoBehaviour
{ 
    // Start is called before the first frame update
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}

当然,目前还不着急去看左侧边栏的功能只是看一下在日常中最常用的,最基本的效果如何.

1.通过注释智能提示代码
按照普通的开发需求,我现在只打注释,看能不能联想出代码来.首先对于playerCtrl ,最最基本的是需要移动速度.那么我就先打个注释
在这里插入图片描述
那么可以发现,通过简单的打出注释即可联想出代码.这一点很不错,那么下一步,我试试让它智能提示出方法体.
在这里插入图片描述
也可以实现提示方法体.这一点buddy与GitHub的copilot没什么不同.而且它也可以和之前自己声明的变量联系起来.当然这里我就不花时间测试了,这么简单的代码一眼看过去,是没有任何问题的.从这里看,buddy具备基本的unity初级人员的开发能力.

在使用的时候它的注释也可以联想出来
在这里插入图片描述

2.通过需求生成一段代码
通过组合键打开需求描述:Alt + K
在这里插入图片描述
那么我这里先做一个玩家移动+相机缓动跟随的功能,那么怎么提问在这里我就不一一写出来了,那样会显得很臃肿.其实怎么与AI沟通也是一个技巧,我会在最后写上我自己总结的经验,这部分经验来自于<ChatGPT提问追问技巧全攻略> 与 <清华104页超详细DeepSeek 从入门到精通>

这里贴上完全由buddy生成的代码:
首先是移动代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCtrl : MonoBehaviour
{ 
   [SerializeField] private float moveSpeed = 5f;
   [SerializeField] private float jumpForce = 10f;
   private Rigidbody rb;
   private bool isGrounded;
   
   void Start()
   {
       rb = GetComponent<Rigidbody>();
   }
   
   void Update()
   {
       Move();
       Jump();
   }
   
   void Move()
   {
       float moveX = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
       float moveZ = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;
       transform.Translate(moveX, 0, moveZ);
   }
   
   void Jump()
   {
       if (Input.GetButtonDown("Jump") && isGrounded)
       {
           rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
           isGrounded = false;
       }
   }
   
   private void OnCollisionEnter(Collision collision)
   {
       if (collision.gameObject.CompareTag("Ground"))
       {
           isGrounded = true;
       }
   }
   
}

当然,如果你对于unity开发比较熟悉应该也能看出来问题:

  1. if (Input.GetButtonDown(“Jump”) && isGrounded) 这里的按键输入并没有为"Jump"的按键,一般的,键盘输入跳跃应该是空格,即为"Space" .
  2. 对于是否在地面上的判断,其实这里有2个问题,第一个是只有OnCollisionEnter的方法,没有OnCollisionEnter的方法,这会导致isGrounded标志位一直为false 第二个问题是对于Rigidbody的获取应该考虑到获取失败的情况.基于此种情况.我对buddy的代码进行一点修改.修改后如下
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor.SceneManagement;
using UnityEngine;
public class PlayerCtrl : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float jumpForce = 10f;
    private Rigidbody rb;
    private bool isGrounded;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        if (rb == null)
        {
            rb = transform.AddComponent<Rigidbody>();
        }
    }

    void Update()
    {
        Move();
        Jump();
    }

    void Move()
    {
        float moveX = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
        float moveZ = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;
        transform.Translate(moveX, 0, moveZ);
    }

    void Jump()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
        {
            Debug.Log(isGrounded);
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            isGrounded = false;
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }

    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = false;
        }
    }
}

多提一句,我在手动敲上OnCollisionExit的时候,它倒是很快给出了我想敲的代码

相机缓动跟随代码:

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

public class CameraFollow : MonoBehaviour
{
       [Header("Camera Settings")]
    [SerializeField] private float smoothSpeed = 0.125f;
    [SerializeField] private Vector3 offset;
    [SerializeField] private float lookAtDistance = 5f;
    [SerializeField] private float dragSpeed = 2f;

    private Transform target;
    private float mouseX, mouseY;

    void Start()
    {
        // 默认跟随玩家(假设玩家对象名为"Player")
        target = GameObject.Find("Player")?.transform;
    }

    void LateUpdate()
    {
        if (target == null) return;

        // 平滑跟随目标
        Vector3 desiredPosition = target.position + offset;
        Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
        transform.position = smoothedPosition;

        // 使相机看向目标
        transform.LookAt(target.position - offset.normalized * lookAtDistance);

        // 鼠标控制视角旋转
        if (Input.GetMouseButton(1)) // 右键拖动
        {
            mouseX += Input.GetAxis("Mouse X") * dragSpeed;
            mouseY -= Input.GetAxis("Mouse Y") * dragSpeed;
            mouseY = Mathf.Clamp(mouseY, -35, 60); // 限制上下视角范围

            Quaternion rotation = Quaternion.Euler(mouseY, mouseX, 0);
            transform.rotation = rotation;
        }
    }

}

这个脚本中也有一些问题.不过问题不大,就是在与对需求的理解上,我给的需求是:相机平滑跟随,并根据鼠辈滑动改变视口. buddy理解成了鼠标滑动是自由视角,而不再看着玩家. 所以我需要再次修改我的需求,并让buddy重新生成

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

public class CameraFollow : MonoBehaviour
{
   [SerializeField] private Transform target;
   [SerializeField] private float followSpeed = 5f;
   [SerializeField] private float rotationSpeed = 10f;
   [SerializeField] private Vector3 offset;
   [SerializeField] private float minDistance = 2f;
   [SerializeField] private float maxDistance = 10f;
   [SerializeField] private LayerMask collisionLayer;
   
   private Vector3 desiredPosition;
   
   void LateUpdate()
   {
       if (target == null) return;
   
       // 计算目标位置
       desiredPosition = target.position + offset;
   
       // 处理鼠标旋转
       RotateView();
   
       // 计算相机方向
       Vector3 direction = target.position - transform.position;
       direction.Normalize();
   
       // 检测碰撞并调整位置
       RaycastHit hit;
       if (Physics.Linecast(target.position, desiredPosition, out hit, collisionLayer))
       {
           desiredPosition = hit.point + direction * minDistance;
       }
   
       // 平滑移动相机
       transform.position = Vector3.Lerp(transform.position, desiredPosition, followSpeed * Time.deltaTime);
   
       // 保持相机看向目标
       transform.LookAt(target.position - direction * maxDistance);
   }
   
   void RotateView()
   {
       // 获取鼠标输入
       float mouseX = Input.GetAxis("Mouse X") * rotationSpeed;
       float mouseY = Input.GetAxis("Mouse Y") * rotationSpeed;
   
       // 旋转相机
       target.Rotate(Vector3.up * mouseX);
       transform.RotateAround(target.position, target.right, -mouseY);
   }
   

}

重新生成后的代码也是有问题,对于处理相机看向玩家处,它的计算完全是反过来的了.所以,这里我需要给它修改一下,那么这次我不再手动修改,而是让它自己修改.

于是我用到左侧的插件栏功能
在这里插入图片描述
Craft 模式很强大,可以通过下面的聊天框 @Add添加多个脚本,进行批量修改.那么这里我只为修改一个,那就是相机跟随代码 所以我对相机跟随代码进行引用
在这里插入图片描述

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

public class CameraFollow : MonoBehaviour
{
    [SerializeField] private Transform target;
    [SerializeField] private float followSpeed = 5f;
    [SerializeField] private float rotationSpeed = 10f;
    [SerializeField] private Vector3 offset;
    [SerializeField] private float minDistance = 2f;
    [SerializeField] private float maxDistance = 10f;
    [SerializeField] private LayerMask collisionLayer;

    private Vector3 desiredPosition;

    void LateUpdate()
    {
        if (target == null) return;

        // 计算目标位置
        desiredPosition = target.position + offset;

        // 处理鼠标旋转
        RotateView();

        // 计算相机方向
        Vector3 direction = target.position - transform.position;
        direction.Normalize();

        // 检测碰撞并调整位置
        RaycastHit hit;
        if (Physics.Linecast(target.position, desiredPosition, out hit, collisionLayer))
        {
            desiredPosition = hit.point + direction * minDistance;
        }

        // 平滑移动相机
        transform.position = Vector3.Lerp(transform.position, desiredPosition, followSpeed * Time.deltaTime);

        // 保持相机看向目标
        transform.LookAt(target.position - direction * maxDistance);
    }

    void RotateView()
    {
        // 获取鼠标输入
        float mouseX = Input.GetAxis("Mouse X") * rotationSpeed;
        float mouseY = Input.GetAxis("Mouse Y") * rotationSpeed;

        // 旋转相机
        // 水平旋转:围绕目标的Y轴旋转相机,而不是旋转目标
        transform.RotateAround(target.position, Vector3.up, mouseX);

        // 垂直旋转:使用正值mouseY,这样鼠标向上移动时相机向上看
        transform.RotateAround(target.position, transform.right, -mouseY);
    }


}

很遗憾,这里的代码仍然有问题.所以,我自己修改.其实就是一个符号的问题.

        transform.LookAt(target.position - direction * maxDistance);

将上方代码中的-号改成+号即可,因为如果是-号的话,那么相机看向的位置一直是相反的方向.

3.联系上下文生成代码

其实做到这个地步,代码还是有问题,比如旋转是可以旋转了,但是它与跟随代码冲突,以及前进的方向不是相机看向的方向,这个功能需要结合playerCtrl与CameraFollow一起修改.

当然,还是要用Craft
在这里插入图片描述

修改完后的代码如下:
playerCtrl

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCtrl : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float jumpForce = 10f;
    [SerializeField] private Transform cameraTransform; // 引用相机的Transform

    private Rigidbody rb;
    private bool isGrounded;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        if (rb == null)
        {
            rb = transform.gameObject.AddComponent<Rigidbody>();
        }

        // 如果没有指定相机,则使用主相机
        if (cameraTransform == null)
        {
            cameraTransform = Camera.main.transform;
        }
    }

    void Update()
    {
        Move();
        Jump();
    }

    void Move()
    {
        // 获取输入
        float moveX = Input.GetAxis("Horizontal");
        float moveZ = Input.GetAxis("Vertical");

        if (moveX == 0 && moveZ == 0) return;

        // 基于相机方向计算移动向量
        Vector3 forward = cameraTransform.forward;
        Vector3 right = cameraTransform.right;

        // 忽略Y轴,保持在水平面上移动
        forward.y = 0;
        right.y = 0;
        forward.Normalize();
        right.Normalize();

        // 计算最终移动方向
        Vector3 moveDirection = (forward * moveZ + right * moveX).normalized;

        // 应用移动
        transform.position += moveDirection * moveSpeed * Time.deltaTime;

        // 如果有移动输入,让玩家朝向移动方向
        if (moveDirection != Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(moveDirection);
        }
    }

    void Jump()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
        {
            Debug.Log(isGrounded);
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            isGrounded = false;
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }

    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = false;
        }
    }
}

cameraFollow

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

public class CameraFollow : MonoBehaviour
{
    [SerializeField] private Transform target;
    [SerializeField] private float followSpeed = 5f;
    [SerializeField] private float rotationSpeed = 10f;
    [SerializeField] private Vector3 offset;
    [SerializeField] private float minDistance = 2f;
    [SerializeField] private float maxDistance = 10f;
    [SerializeField] private LayerMask collisionLayer;

    private Vector3 desiredPosition;

    void LateUpdate()
    {
        if (target == null) return;

        // 计算目标位置
        desiredPosition = target.position + offset;

        // 处理鼠标旋转
        RotateView();

        // 计算相机方向
        Vector3 direction = target.position - transform.position;
        direction.Normalize();

        // 检测碰撞并调整位置
        RaycastHit hit;
        if (Physics.Linecast(target.position, desiredPosition, out hit, collisionLayer))
        {
            desiredPosition = hit.point + direction * minDistance;
        }

        // 平滑移动相机
        transform.position = Vector3.Lerp(transform.position, desiredPosition, followSpeed * Time.deltaTime);

        // 保持相机看向目标
        transform.LookAt(target.position + direction * maxDistance);
    }

    void RotateView()
    {
        // 获取鼠标输入
        float mouseX = Input.GetAxis("Mouse X") * rotationSpeed;
        float mouseY = Input.GetAxis("Mouse Y") * rotationSpeed;

        // 旋转相机
        // 水平旋转:围绕目标的Y轴旋转相机,而不是旋转目标
        transform.RotateAround(target.position, Vector3.up, mouseX);

        // 垂直旋转:使用正值mouseY,这样鼠标向上移动时相机向上看
        transform.RotateAround(target.position, transform.right, -mouseY);
    }


}

那么,从这个动图来看问题还是存在,其一,360度环绕有问题,其二,没有相机避开遮挡之后没有回到原来的距离.

那么还需要细心的修改代码

那么就是代码中的offset的问题,其中offset是个定值,而有环绕观察的功能,offset不能是个定值否则它就会一直缓动到固定的位置.所以,在控制环绕的代码中对offset进行一个赋值.

 void RotateView()
    {
        // 获取鼠标输入
        float mouseX = Input.GetAxis("Mouse X") * rotationSpeed;
        float mouseY = Input.GetAxis("Mouse Y") * rotationSpeed;

        // 旋转相机
        // 水平旋转:围绕目标的Y轴旋转相机,而不是旋转目标
        transform.RotateAround(target.position, Vector3.up, mouseX);

        // 垂直旋转:使用正值mouseY,这样鼠标向上移动时相机向上看
        transform.RotateAround(target.position, transform.right, -mouseY);

        // 限制垂直旋转角度
        Vector3 eulerAngles = transform.eulerAngles;
        if (eulerAngles.x > 180f)
            eulerAngles.x -= 360f;
        eulerAngles.x = Mathf.Clamp(eulerAngles.x, -80f, 80f);
        transform.eulerAngles = eulerAngles;

        // 更新offset
        offset = transform.position - target.position;
    }

那么最后的成品如下:

请添加图片描述

总的来说我没有任何自己的想法,只是用buddy来生成代码,对于它里面的错误进行修改.其实这个过程持续没有超过30分钟,这种开发的效率已经是很可观了(毕竟没有高深的东西).那么我很想看看有点技术含量的东西,buddy的表现如何.

比较难的功能实现

比如软体模拟.让它生成软体模拟的代码,并且使用骨骼球的方式.

这个结果让我很意外

首先它扫描了我的项目结构,并且把生成的代码放在了正确的位置.对于物理计算公式也是正确的.为什么我要用软体模拟呢?因为几年前.我就研究过.那时候只能通过论文来研究,最后是借助了bullet引擎做出来的软体.而现在buddy仅仅用了大概10分钟左右的时间,就完成了软体模拟,它自动生成了近1000行代码,并没有任何报错,最后居然还给我生成了一个使用文档!

在这里插入图片描述

我没有做任何修改,按照指导文档中的操作在unity中进行设置.调整了几个参数.效果如下;

请添加图片描述

这个结果令人震惊,因为不久之前我也试过deepseek与元宝,没有一个是一次就能跑通的,这个buddy我对它的表现还是很满意的.

BlenderMCP AI 建模

在左侧的插件中点击在这里插入图片描述
因为我发现了blender的自动建模插件.这令我很意外.所以试一试,看看好不好用,buddy真是给我诸多惊喜.没想到编程可以,居然连自动建模也可以.

这个插件有些靠后,选择它下载即可,在下载的时候可能会提示安装失败,缺少uv 或者什么ux一类的
在这里插入图片描述
windows平台右键windows图标:现在powershell (管理员)

用以下命令开始安装配套程序

安装UV ,打开powershell (管理员)
执行以下代码:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/0.7.3/install.ps1 | iex"

在这里插入图片描述

检查安装是否完成:

powershell -c "irm https://astral.sh/uv/install.ps1 | more"

在这里插入图片描述
做完之后回到vscode,如果你的vscode不是管理员权限打开的,还需要你重新用管理员权限打开.然后点击安装即可

安装之后如下:
在这里插入图片描述

那么再打开blender 安装vscode 中BlenderMCP中的addon.py插件.地址是 : 点此处跳转

安装好如下

在这里插入图片描述

界面中即可看到安装完毕

在这里插入图片描述

然后点击Connect MCP server 上面的两个选项可以都不选,因为选择了的话网络不通会有问题.

然后打开duddy的Craft ,让它建立一个简单的模型:

在这里插入图片描述

然后按下F12 渲染

最后做出的酒杯渲染效果图:
在这里插入图片描述
这个我没有做任何模型的点线面修改,纯AI自己生成的.

以上是我使用buddy的使用经历.个人感觉比copilot的功能多,很值得各位去尝试.

AI提问技巧(个人经验版)

1.简洁明了的提问 不需要礼貌用语 避免模糊的提示 (如帮我写段代码),需要限制AI的思考范围.例如:用unity技术栈开发一个用户登录的功能,并且用户可以扫码登录.
2.区分问题类型 让Ai知道你是需要改bug,还是要生成代码.(如这个地方内存泄漏,分析原因)
3.结构化提问 像流程图一样.让AI从1-100来做,避免直接让它做一个大项目(如 1.设计一个数据表,用来存放玩家信息 2.编写对应的序列化器(不要使用XX方法) 3.抽象出一个接口供unity客户端调用)
4.术语要专业 有些术语是各位私下里的叫法,而AI却不能明白.所以需要使用标准的专业术语(如 加密密码 改成 哈希加密 MD5加密等)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Unity-Plane

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值