Unity API

Unity脚本支持的语言:

3.x 4.x 5.x:C#、JavaScript、BOO、C与C++ 等。

Unity2017以后:C#

修改Unity范本:

路径:安装目录\Editor\Data\Resources\ScriptTemplates

修改范本:81-C# Script-NewBehaviourScript.cs.txt

怎么引用Unity中的类?

创建自己的Debugl类:

创建平台:选类库

框架选:3.5(重选框架:项目=》最下面属性=》选择框架)

引入所有类库:E:\Unity2018.4.8f1\Editor\Data\Managed\UnityEngine

直接复制类库到自己工程目录下面

开发工具:

MonoDevelop:MonoDevelop  是个适用于 Linux、Mac  OS  X   和 Microsoft  Windows   的开放源代码集成开发环境,主要用来开发 Mono   与 .NET  Framework   软件。

VS2019:

设置VS2019为开发工具:

debug类

Debug.Log("控制台输出 信息");

Debug.LogWarning("控制台输出 警告 信息");

Debug.LogError("控制台输出 错误 信息");

Debug.Log与Print区别?

Print:print  是MonoBehaviour的一个成员。print  必须要继承  MonoBehaviour  类,

Debug.Log:Debug则是一个独立的、密闭的类。Debug不需要继承  MonoBehaviour  类,

Application类:

1.使用宏定义和Application.platform判断运行平台

        //Android平台

#if UNITY_ANDROID

        debug.log("Android");

#endif
        //苹果平台

#if UNITY_IPHONE

        debug.log("IOS");

#endif
        //Windows平台

#if UNITY_STANDALONE_WIN

        Debug.Log("Windows");

#endif

2.Application.platform判断平台:

if (Application.platform == RuntimePlatform.Android)

        {

            Debug.Log("Android");

        }else if(Application.platform == RuntimePlatform.IPhonePlayer)

        {

            Debug.Log("IOS");

        }

        else if (Application.platform == RuntimePlatform.WindowsEditor)

        {

            Debug.Log("Window");

        }

SceneManager类

跳转场景的方法

//当前跳转场景方法
SceneManager.LoadScene(1);//场景序号
SceneManager.LoadScene("Scene2");//场景名称

MonoBehaviour类

MonoBehaviour类:是一个基类,所有 Unity 脚本都派生自该类

作用

让脚本可以像组件一样挂在物体上。

包含脚本生命周期:

Awake()函数是加载场景时运行,就是说在游戏开始之前初始化变量或游戏状态。

OnEnable():当对象变为可用或激活状态时被调用

Start()函数是在第一次启动时执行,用于游戏对象的初始化,在Awake()函数之后。

FixedUpdate()与Update()函数相似,但是每个固定物理时间间隔调用一次,用于物理状态的更新。

Update()是在运行时每一帧必执行的函数,用于更新游戏场景和状态。

LateUpdate()是在Update()函数执行后再次被执行。

OnGUI():渲染和处理OnGUI事件

OnDisable():当前对象不可用或非激活状态时被调用

OnDestroy():当前对象被销毁时调用

详细脚本生命周期看下图:

Collision事件

OnCollisionEnter函数:当碰撞体或者刚体与其他碰撞体或者刚体开始接触时调用

OnCollisionStay函数:当碰撞体或者刚体与其他碰撞体或者刚体保持接触时调用

OnCollisionExit函数:当碰撞体或者刚体与其他碰撞体或者刚体停止接触时调用

Trigger事件

OnTriggerEnter函数:当其他碰撞体进入触发器时调用

OnTriggerStay函数:当其他碰撞体停留触发器时调用

OnTriggerExit函数:当其他碰撞体离开触发器时调用

GameObject类

 GameObject类继承于Object类,是Unity场景里面所有实体的基类。

1.物体状态:

Debug.Log(obj.activeSelf);  //显示物体激活状态(只读)

obj.SetActive(true);//设置物体的激活状态

SetActive显示/隐藏游戏对象:在Unity中,要激活游戏对象的方法就是使用SetActive(),就是说通过此方法让游  戏对象显示或者隐藏。

2.名字、标签、层:

Debug.Log(obj.name); //输出物体名字

Debug.Log(obj.tag);//输出标签

Debug.Log(obj.layer);//输出层(删除数字)

3.查找方法:

通过对象名称(Find方法)GameObject.Find

通过标签获取单个游戏对象(FindWithTag方法)

通过标签获取多个游戏对象(FindGameObjectsWithTags方法)

//Find只能查找激活的物体
obj3=GameObject.Find("Cube");

//通过标签查找物体
obj3=GameOject.FindGameObjectWithTag("MainCamera");

//通过标签获取多个游戏对象
objs=GameOject.FindGameObjectWithTag("MainCamera");

物体:

CreatPrimitive方法是创建一个原生几何体,也就是带有基本网格渲染器和相应碰撞器的游戏对象。

例如:Cube、Sphere、Capsule等。

GameObject.CreatePrimitive(PrimitiveType.Cube);

Instantiate实例化:Unity提供克隆游戏对象的方法

Instantiate(GameObject);

Instantiate(GameObject, position, rotation);
//创建基础物体
GameObject.CreatePrimitive(PrimitiveType.Cube);

//实例化基础物体,实例化物体后面带(Clone)
GameObect obj9=(GameObject) Instantiate(obj3);

//obj.name="obj3";
//创建空物体
GameObject obj1=new GameObject("NullObject");

Destory销毁:Destory()是主要用于销毁游戏对象以及组件,但不会再引用那个被销毁的对象

Destroy(GameObject);

Destroy(GameObject, time);

组件:

GetComponent获取组件:访问游戏对象的组件的方法

GameObject.GetComponent<type>()

增加组件:AddComponent

gameObject.AddComponent("SphereCollider")  as  SphereCollider;

销毁组件:

Destroy(cube.GetComponent<Rigidbody>());

状态:enable

创建墙壁

Input类

Input类是输入系统的接口。使用这个类能够读取输入管理器 设置的按键,以及访问移动设备的多点触控或加速感应数据。

鼠标:

KeyCode键值

Input.GetMouseButton(0)

Input.GetMouseButtonDown(0)

Input.GetMouseButtonUp(0)

键盘:

Input.GetKey(+键值)

Input.GetKeyDown(+键值)

Input.GetKeyUp(+键值)

虚拟轴

键盘

Input.GetAxis("Horizontal")

Input.GetAxis("Vertical")

鼠标

Input.GetAxis("Mouse X")

Input.GetAxis("Mouse Y")

Input.GetAxis("Mouse ScrollWheel")

InputManager简介

Unity提供了自定义按键的功能,使用时需要在输入管理器中配置自定义按键,首先在Unity导航菜单栏中选中“Editor”->“Project  Setting”->“Input”菜单项,打开输入管理器界面,然后进行修改自定义按键即可。

按键检测

Input.anyKey:按键按住时为true

Input.anyKeyDown:按键按下时为ture

鼠标位置

mousePosition鼠标当前的像素坐标位置。(只读)

Transform类

场景里的每个对象都含有Transform,用来存储并控制物体的位置、旋转和缩放。

作用:

① 负责游戏对象的变换

② 维持父子关系

在Hierarchy面板可以看到,每一个Transform可以有一个父级,允许分层次管理位、旋转和缩放。

父子关系

在Hierarchy视窗中,通过把一个游戏对象拖放到另一个游戏对象之上来创建父物体,这样将创建一个父子关系       来关联这两个游戏对象。

物体间父子关系作用

当一个游戏对象是另一个游戏对象的父物体时,其子游戏对象会随着父游戏对象移动、旋转和缩放。

举个例子来说,你的胳膊(子物体)属于你的身体(父物体),当你旋转身体时,你的胳膊也会跟着旋转一样。

任何物体都可以有多个子物体,但只能有一个父物体。通过构建物体间的父子关,在开发过程中提供了很大方便。

SetParent

设置变换的父级。

位置:

localPosition:相对于父级的变换的位置

Position:在世界坐标系中,transform的位置

eulerAngles:旋转作为欧拉角度

localEulerAngles:相对于父级的变换的旋转欧拉角度

rotation :在世界坐标系中物体变换的旋转角度作为Quaternion储存

localRotation:相对于父级的旋转

移动:

沿着物体本身坐标轴

沿着世界坐标轴

Translate

根据 translation 的方向和距离移动变换

transform.position:指定物体在世界坐标下的位置。

transform.Translate:指物体相对位移的单位。

transform.Rotate:指物体旋转。

transform.eulerAngles:指物体的角度。

transform.localScale:指物体的缩放,注意的是缩放各个轴不能为0,否则会消失

Find

可以查找隐藏子物体

GetChild:

按索引返回变换子项

0开头

LookAt:

旋转变换,使向前矢量指向 target 的当前位置

始终是Z轴看向目标点

Rigidbody类

可使游戏对象在物理系统的控制下来运动。

AddForce:此方法被调用时,会施加给刚体一个瞬时力。在力的作用下,会产生一个加速度进行运动。

AddTorque:此方法被调用时,会给刚体添加一个扭矩。

Sleep:此方法可使刚体进入休眠状态,且至少休眠一帧,一般在Awake()函数里面。

WakeUp:此方法使刚体从休眠状态唤醒。

Time类

Time类是在Unity中获取时间信息的接口类,可以用来计算时间的消耗,只有静态属性。

Time.time:当前游戏已经运行的时间

Time.deltaTime:上一帧消耗的时间;

timeScale:时间流逝的缩放。可用于慢动作效果。

        

Mathf类

Mathf是Unity提供的所有数学计算时需要用到的函数

Mathf.Abs()------取绝对值

Mathf.Ceil()------向上取整,返回值为Float类型

Mathf.CeilToInt()------向上取整,返回值为Int类型

Mathf.Floor()--------向下取整,返回值为Float类型

Mathf.FloorToInt()--------向下取整,返回值为Int类型

Mathf.Round()--------四舍五入,返回值为Float类型

Mathf.RoundToInt()--------四舍五入,返回值为Int类型

Mathf.Pow(float x,float y)--------返回x的y次方

Mathf.Sqrt(float x)-----------返回x的平方根

Mathf.DeltaAngle(float current,float target)---------返回两个角夹角的最小值

Mathf.ClosestPowerOfTwo(float x)------------返回2的x次方

Mathf.Clamp

Mathf.Clamp(float current,float min,float max)

限制 current的值在min,max之间,如果current大于max,则返回max,如果current小于min,则返回min,否者返回current;

Mathf.Lerp(float a, float b, float t)--------线性插值,t为一个比例,范围[0,1]

t=0的时候返回a,t=1的时候返回b,t=0.5时返回(a+b)/2     先快后慢

Mathf.MoveTowards(float current, float target, float maxDelta)------与Mathf.Lerp本质上是一样的       匀速

如果maxDelta为负数,current的值将远离target

Mathf.PingPong(float t,float length)----返回值在0和length之间

Random类

用于产生随机数。

Random.Range第二个数为

    整数:  第二个数取不到

    小数:  第二个数能取到

Application类

Coroutine协同

在主线程运行的同时开启另一段逻辑处理,来协助当前程序的执行

协程不是多线程,Unity的协程是在每帧结束之后去检测yield的条件是否满足

Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?

仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用

支持:如果同时你要处理很多事情或者与Unity的对象互动可以用thread,否则使用coroutine。

注意:C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象

例子

StartCoroutine("MyFun");//调用协程

StopCoroutine("MyFun");//终止协程

StopAllCoroutines();//终止所有协程

IEnumerator MyFun()

    {

        Debug.Log("协同被调用1");

        yield return null;

        Debug.Log("协同被调用2");

    }

Vector类

简写

up  =Vector3(0, 1, 0)

down    用于编写 Vector3(0, -1, 0) 的简便方法。

left    用于编写 Vector3(-1, 0, 0) 的简便方法。

right   用于编写 Vector3(1, 0, 0) 的简便方法。

forward 用于编写 Vector3(0, 0, 1) 的简便方法。

back    用于编写 Vector3(0, 0, -1) 的简便方法。

one 用于编写 Vector3(1, 1, 1) 的简便方法。

zero    用于编写 Vector3(0, 0, 0) 的简便方法。

Magnitude:返回该向量的长度。(只读)

Lerp:在两个向量之间进行线性插值

MoveTowards:向指定点移动(注意写在Update里)

sqrMagnitude:返回该向量的平方长度

normalized:获取单位化后的向量(只读)。

Cross():向量叉乘。

Dot():向量点乘。

Project():计算向量在另一向量上的投影。

Angle():返回两个向量之间的夹角。

Distance():返回两个向量之间的距离

Quaternion类

    Euler返回一个围绕 Z 轴旋转 z 度、围绕 X 轴旋转 x 度、围绕 Y 轴旋转 y 度的旋转

应用实例

Quaternion quaternion_T;
void Start()
{
    quaternion_T=Quaternion.Euler(100,30,200);
    print("Euler to Quaternion"+quaternion_T);
}

collision类

#region 碰撞检测:两个都是碰撞器,可以获取别的碰撞器

    自己是碰撞器-别人也是碰撞器   ****

    碰撞检测,检测的是别人(不是挂脚本的物体)

    //private void OnCollisionEnter(Collision collision)

    //{

    //    Debug.Log("发生碰撞时");

    //    Debug.Log(collision.collider.name); //碰撞物体名字

    //    Debug.Log(collision.collider.gameObject); //碰撞物体

    //    Debug.Log(collision.collider.tag);    //碰撞物体标签

    //}

    //private void OnCollisionStay(Collision collision)

    //{

    //    Debug.Log("碰撞时");

    //}

    //private void OnCollisionExit(Collision collision)

    //{

    //    Debug.Log("结束碰撞时");

    //}

    自己是碰撞器,别人是触发器,触发不了碰撞检测函数

    自己是触发器,别人是碰撞器,触发不了碰撞检测函数

    #endregion

    #region 触发检测:只要有一个触发器,就可以触发 触发检测函数

    //自己是碰撞器,别人是触发器,可以触发 触发检测函数

    //自己是触发器,别人是碰撞器,可以触发 触发检测函数

    //自己是触发器,别人是触发器,可以触发 触发检测函数

    private void OnTriggerEnter(Collider other)

    {

        Debug.Log("发生碰撞时");

        Debug.Log(other.name); //碰撞物体名字

        Debug.Log(other.gameObject); //碰撞物体

        Debug.Log(other.tag);    //碰撞物体标签

    }

    private void OnTriggerStay(Collider other)

    {

        Debug.Log("碰撞时");

    }

    private void OnTriggerExit(Collider other)

    {

        Debug.Log("结束碰撞时");

    }

    #endregion

射线

第一种写法

#region 射线第一种写法

        Camera.main  获取主摄像机

        //Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        //RaycastHit hit;//存放射线碰撞信息

        //if (Physics.Raycast(ray, out hit))

        //{

        //    Debug.DrawLine(Camera.main.transform.position, hit.point, Color.red);

        //    Debug.Log(hit.collider.name);  //射线打的物体名字

        //    Debug.Log(hit.collider.gameObject);//射线打到的物体

        //    Debug.Log(hit.collider.tag);//射线打到物体的标签

        //    Debug.Log(hit.point);//射线与物体的碰撞的点坐标

        //}

        #endregion

  第二种写法

  #region 射线第二种写法

        //Ray ray = new Ray(obj1.transform.position, obj2.transform.position);

        //RaycastHit hit;//存放射线碰撞信息

        //if (Physics.Raycast(ray, out hit))

        //{

        //    Debug.DrawLine(obj1.transform.position, obj2.transform.position, Color.red);

        //    Debug.Log(hit.collider.name);  //射线打的物体名字

        //    Debug.Log(hit.collider.gameObject);//射线打到的物体

        //    Debug.Log(hit.collider.tag);//射线打到物体的标签

        //    Debug.Log(hit.point);//射线与物体的碰撞的点坐标

        //}

        #endregion

  高级写法

#region 射线高级写法

        //射线另一种写法

        Ray ray = new Ray(obj1.transform.position, obj2.transform.position);

        //Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        RaycastHit hit;

        //if (Physics.Raycast(ray, out hit))

        if (Physics.Raycast(ray, out hit, 100, 60))//100是射线的长度  2 3 4 5

        //if (Physics.Raycast(ray, out hit, 100, ~(1 << 5)))//100是射线的长度

        {

            Debug.Log(hit.collider.name);

        }

        //必须加上最大长度 32层

        //(1 << layerNumber)只检测某一层(layerNumber表示layer层的标号)

        //~(1 << layerNumber)不检测某一层,其余都检测

        //(1 << layerNumber)|(1 << layer2Number)只检测某2个层

        //int a = 1;  //=> 001

        //int b = 4;  //=> 100

        //Debug.Log(a | b); //==101

         1010101001==>     1 3 5 7   9

        /// 111100

        #endregion

WWW类

void Start()

    {

        //Debug.Log("Start调用1");

        //StartCoroutine("MyFun");//调用协程

        //Debug.Log("Start调用1");

        //StopCoroutine("MyFun");//终止协程

        //StopAllCoroutines();//终止所有协程

        StartCoroutine(MyFun());//调用协程

        StopCoroutine(MyFun());//终止不了协程

    }

    IEnumerator MyFun()

    {

        yield return new WaitForSeconds(4);//等待4秒

        Debug.Log("协同被调用1");

        yield return null;  //返回空

        Debug.Log("协同被调用2");

    }

实例1

​
public Texture img;

    void Start()

    {

        StartCoroutine("LoadingImage");

    }

    IEnumerator LoadingImage()

    {

        string url= "https://img2.baidu.com/it/u=1513792956,895994420&fm=15&fmt=auto&gp=0.jpg";

        WWW www = new WWW(url);

        yield return www;

        if (www.error == null)

        {

            img = www.texture;

        }

    }

    private void OnGUI()

    {

        if(img!=null)

            GUI.Label(new Rect(0, 0, img.width, img.height), img);

}

​

WWWFrom类

​
public string url = "http://127.0.0.1:8089/SharedHome/Owner.aspx";

    void Start()

    {

        StartCoroutine("UpData"); 

    }

    IEnumerator UpData()

    {

        WWWForm wwwForm = new WWWForm();

        wwwForm.AddField("Id","999");

        wwwForm.AddField("Passworld", "12345");

        WWW www = new WWW(url, wwwForm);

        yield return www;

        if (www.error == null)

        {

            Debug.Log("上传完成");

        }

        else

        {

            Debug.Log(www.error);

        }

}

​

WWW事例1

​
public Texture img;

    public string url = "http://127.0.0.1:8089/1.Txt";

    public string urlTxture = "http://127.0.0.1:8089/01.jpg";

    public string urlTxture2 = "http://127.0.0.1:8089/02.mp4";

    void Start()

    {

        //StartCoroutine("LoadingImage");

        //StartCoroutine("LoadingTxt");

        //StartCoroutine("LoadingTexture");

        //StartCoroutine(LoadingTexture(urlTxture));

        //StartCoroutine("Load");

    }

    private WWW www;//下载网址信息

    public string LoadPro;//下载进度

    public IEnumerator Load()

    {

        www = new WWW(urlTxture2);

        yield return www;

        while (!www.isDone) //没有 下载完成

        {

            LoadPro = (((int)(www.progress * 100)) % 100) + "%";//98 %

            Debug.Log("进度:" + LoadPro);

            yield return 1;

        }

        if (www.error != null) //报错

        {

            Debug.Log("Loading error:" + www.url + "\n" + www.error);//打印错误信息

        }

        else

        {

            LoadPro = "100%";

            Debug.Log("下载完成");

        }

    }

    /// <summary>

    /// 读取图片

    /// </summary>

    IEnumerator LoadingTexture(string url)

    {

        WWW www = new WWW(url);

        yield return www;

        //www.isDone//属性以查看下载是否完成

        //www.progress//下载进度(只读)

        if (www.error == null)

        {

            img=www.texture;

        }

        else

        {

            Debug.Log(www.error);

        }

    }

    /// <summary>

    /// 读取txt信息

    /// </summary>

    IEnumerator LoadingTxt()

    {

        WWW www = new WWW(url);

        yield return www;//等待访问结束

        if (www.error == null) //如果下载期间出错,则返回错误消息(只读)

        {

            Debug.Log(www.text);  

        }

        else

        {

            Debug.Log(www.error);

        }

    }

    IEnumerator LoadingImage()

    {

        string url= "https://img2.baidu.com/it/u=1513792956,895994420&fm=15&fmt=auto&gp=0.jpg";

        WWW www = new WWW(url);

        yield return www;

        if (www.error == null)

        {

            img = www.texture;

        }

    }

    //private void OnGUI()

    //{

    //    if(img!=null)

    //        GUI.Label(new Rect(0, 0, img.width, img.height), img);

    //}

​

UnityWebRequest 类

事例1

​
public string url= "http://127.0.0.1:8089/02.mp4";

    void Start()

    {

        StartCoroutine("LoadingDate");

    }

    IEnumerator LoadingDate()

    {

        UnityWebRequest request = UnityWebRequest.Get(url); //UnityWebRequest对象用于与 Web 服务器进行通信。

        /*

            Get 为 HTTP GET 创建 UnityWebRequest。

            Head 创建一个经配置可发送 HTTP HEAD 请求的 UnityWebRequest。

            Post 创建一个经配置可通过 HTTP POST 向服务器发送表单数据的 UnityWebRequest。

            Put 创建一个经配置可通过 HTTP PUT 将原始数据上传到远程服务器的 UnityWebRequest。

        */

        request.SendWebRequest();//开始与远程服务器通信

        /* isHttpError:当此 UnityWebRequest 接收到指示错误的 HTTP 响应代码后,返回 true。(只读)

         * isNetworkError:当此 UnityWebRequest 遇到系统错误后,返回 true。(只读)

         * error:一个可读字符串,用于描述此 UnityWebRequest 对象在处理 HTTP 请求或响应时遇到的任何系统错误。(只读)

         */

        if (request.isHttpError || request.isNetworkError)

        {

            Debug.Log("当前的下载发生错误" + request.error);

            yield break;

        }

        while (!request.isDone) //isDone:当 UnityWebRequest 结束与远程服务器的通信后,返回 true。(只读)

        {

            print("当前的下载进度为:" + request.downloadProgress); //   downloadProgress 返回一个 0.0 和 1.0 之间的浮点值,用于表示从服务器下载主体数据的进度。(只读)

            yield return 0;

        }

        if (request.isDone)

        {

            //将下载的文件写入

            using (FileStream fs = new FileStream(Application.dataPath + "/Test.MP4", FileMode.Create))

            {

                byte[] data = request.downloadHandler.data;  //downloadHandler:拥有对 DownloadHandler 对象的引用,该对象可管理此 UnityWebRequest 从远程服务器接收的主体数据

                fs.Write(data, 0, data.Length);

            }

        }

    }

​

事例2

​
void Start()

    {

        StartCoroutine(Get());

        StartCoroutine(Post());

    }

    IEnumerator Get()

    {

        UnityWebRequest webRequest = UnityWebRequest.Get("http://www.baidu.com");

        yield return webRequest.SendWebRequest(); //开始与远程服务器通信。

        //异常处理,很多博文用了error!=null这是错误的,请看下文其他属性部分

        if (webRequest.isHttpError || webRequest.isNetworkError)

            Debug.Log(webRequest.error);

        else

        {

            Debug.Log(webRequest.downloadHandler.text);

        }

    }

    IEnumerator Post()

    {

        WWWForm form = new WWWForm();

        //键值对

        form.AddField("key", "value");

        form.AddField("name", "mafanwei");

        form.AddField("blog", "qwe25878");

        UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com", form);

        yield return webRequest.SendWebRequest();

        //异常处理,很多博文用了error!=null这是错误的,请看下文其他属性部分

        if (webRequest.isHttpError || webRequest.isNetworkError)

            Debug.Log(webRequest.error);

        else

        {

            Debug.Log(webRequest.downloadHandler.text);

        }

    }

​

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值