zoukankan      html  css  js  c++  java
  • Unity以及游戏源码

    基本认识

    1. FixedUpdate:每秒50次刷新:50帧,注意条件变量的控制(二段跳)

    2. 单词

      1. gravity:重力

      2. Rigdbody:刚体

      3.  

    Unity

    1. 组件名在vs中不能更改,且vs要求组件名必须首字母大写;

    2. 视角跟随:在unity中选中GameObject为Sphere

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

      public class CameraControler : MonoBehaviour
      {
         public GameObject Sphere;//在unity中选中GameObject为Sphere
         private Vector3 offset;
         // Start is called before the first frame update
         void Start()
        {
             offset = transform.position - Sphere.transform.position;
        }

         // Update is called once per frame
         void LateUpdate()
        {
             transform.position = Sphere.transform.position + offset;
        }
      }

      分辨率:一个格子100dp=10*10;

      物体碰撞(2d):

      1. 物体设置为Rigidbody、Boxcollider,地面设置为Rigidbody并将bodytype修改为Kinematic、Boxcollider

      2. 碰撞会产生微小形变,可能会穿模,将主角的Rigidbody中的Interpolate改为Interpolate去除碰撞形变

    物体运动

    https://www.bilibili.com/video/BV14V411r7Tr?p=2视频教学

    Kinematic:开启运动学,开启后不再受力的影响,只能通过Transform属性来操作。

    1. 初级运动

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

      public class Character : MonoBehaviour
      {
         public float speed = 3f;
         public Rigidbody2D rig;
         public float jumpForce;
         // Start is called before the first frame update
         void Start()
        {
             rig = GetComponent<Rigidbody2D>();
             jumpForce = 300f;
        }

         // Update is called once per frame
         void Update()
        {
             if (Input.GetKeyDown(KeyCode.K))
            {    //如果按下空格

                 rig.AddForce(new Vector2(0, jumpForce));   //给刚体一个向上的力

            }
             float moveX = Input.GetAxisRaw("Horizontal");//控制水平方向A:-1 D:1 0
             //float moveY = Input.GetAxisRaw("Vertical");//控制数值方向S:-1 W:1 0

             Vector2 position = transform.position;
             position.x += moveX * speed * Time.deltaTime;
             transform.position = position;
        }
      }

       

    2. 高级

      1. 改为没有平滑过渡Editor--Project setting--Input--Gravity、Sensetivity修改为1000,与fire1相同

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

        public class Character : MonoBehaviour
        {
           public float WalkSpeed;
           public float AccelerrateTime;
           public float DecelerateTime;

           Rigidbody2D Rig;
           float velocityX;

           private void Awake()
          {
               Rig = GetComponent<Rigidbody2D>();
          }
           private void FixedUpdate()
          {
               if (Input.GetAxisRaw("Horizontal") < 0)
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60, ref velocityX, AccelerrateTime), Rig.velocity.y);
              }
               else if (Input.GetAxisRaw("Horizontal") > 0)
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60*(-1), ref velocityX, AccelerrateTime), Rig.velocity.y);
                   //使用加速时间控制启动、停止快慢
              }
               else if (Input.GetAxisRaw("Horizontal") == 0)
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, 0, ref velocityX, AccelerrateTime), Rig.velocity.y);
              }
          }
        }

    使用

    在Edit->project setting -> input 处可以对按键细节进行设置: 20200109141230272 扩展size ,即可添加按键配置。 Name:名称,调用或在外部设置的时候需要使用该名 Negative Button :缺省值为-1的按键 Positive Button :缺省值为1的按键 Alt Negative Button :备用的缺省值为-1的按键 Alt Positive Button :备用的缺省值为1的按键 Dead: 输入阈值, 触摸或者摇杆大于这个值才会触发输入 Gravity:表示松开按键时,从端点1或-1返回缺省值0时的速度 Sensitivity:按下按键时,从缺省值0到1或-1时的速度 Snap: 当触发反向操作时,当前值是否立即归零 Invet:是否取反值 Type:预设输入设备类型,可选键盘与鼠标按键、手柄、鼠标移动 Axis:装置选择,例如一个手柄有两个十字键两个摇杆,那么可以在这里设置当前设定作用于哪个装置 Joy Num: 手柄编号。指定连接的哪个设备 需要说明的是,在输入管理器中设置的输入基本上都是返回-1 - 1 区间的值。这比返回true false要好很多,因为优化输入体验的时候,比如我们希望根据按压力度来调整跳跃距离,又或者我们希望根据摇杆的摇摆程度来控制车辆的方向盘,都比较合适

    函数说明

    Rig.velocity:刚体的速度:矢量,

    参数说明

    Parameters,它就是使用Animator来切换动作的灵魂。可以把它理解为实现动作的条件,通过改变它来判断满足什么条件执行什么动作。点击右边的+号,可以看到有4个类型:Float,Int,Bool,Trigger。

    绘制背景

    1. 创建tilemap

    2. 设置sortinglayer:通过Edit/Project Settings/Tags & Layers打开Sorting Layers创建*排列层*并调整它们的位置

    3. 放入背景,设置每个tilemap单元格的像素(设置tilemap的scale大小,自己调试)

      第一次人物做的太小,导致画地图时地图方块无法占满单个格子

    4. 调试物块大小:将物块放入tilepalete,在inspector界面中调整图片像素

    设置地图

    1. 在对应的tilemap里边添加碰撞器,刚体

    2. 单独的每一块碰撞器,发现角色卡在某个位置不能移动,解决方法:将每个碰撞器合并成整体的复合碰撞器

      1. Tilemap Collidor 2d中选择used by Composite

      2. 添加Composite Collidor 2d

    3. 调整TileMap碰撞点

      在进行爬坡测试的时候,出现了一个问题就是斜坡的瓦片碰撞点不能和瓦片重合,且凹凸不平,运行体验不佳。

      不是正方形的瓦片的话,TileMap的碰撞点自动设置可能很奇怪,直接TileMap设置碰撞器的话,可能会有凹凸不平的情况,且凹凸不平的形状不能和瓦片完全重合。

      出现这个问题可能需要回到一开始编辑图片,在Sprite Editor里面,左边的红框选择第三个Custom Physics Shape,然后点击需要修改碰撞点的方形块,然后点击Generate就可以修改碰撞点。

    4. 物体勾选IsTriger:物体可以被穿过但仍视为有效碰撞,用于制作陷阱或者拾取道具

    动画制作

    1. 创建空动画

    2. 将动画拉入主角,自动生成动画控制器

    3. 点击Animator,右键创建blendtree

    4. 点击blendtree,再双击,添加之前创建的空动画

    5. 选择主角,在animation处添加图片,生成动画

    动画重写

    1. 已有Enermy1动画效果,在AnimationControllers文件夹内空白处右键,依次选择Create->Animator Override Controller,创建了一个动画重写控制器,我们命名为Enemy2

    2. 可以看到这个重写控制器右侧Inspector窗口内有个Controller选项,可以选择继承哪个动画控制器。在这里,我们可以把Enemy1直接拖入到输入框,或者点击输入框右侧的小圆圈选择Enemy1。

    3. 继承Enemy1的动画控制器后,还需要把美术资源也替换掉。Enemy1Attack改写成Enemy2Attack,Enemy1Idle改写成Enemy2Idle,这样重写控制器就配置好了。

    4. 这时候,怪物2的Animator组件使用的控制器还是Enemy1。选择Enemy2游戏对象,在Animator组件的Controller选项点击右侧小圆圈,在弹出的窗口中选择Enemy2即可。

    5. 这时候运行游戏,可以看到怪物2的动画正常。

    6. 通过这样重写控制器,以后在怪物1的动画控制器添加逻辑的时候,怪物2自动继承,不需要再额外给怪物2添加一样的逻辑。我们这个项目才2个小怪,如果怪物类型或者动画类型再多一点,重写控制器就非常有必要。而且修改起来也只需要改一个地方即可,非常方便。其实个人觉得和Prefab预制件有点相似。

    链接:https://www.jianshu.com/p/5622f6db56b7

    game

    实现高度手感跳跃

    public float LowJumpMultiplier;
       bool IsJumping;

       //触地判定
       public Vector2 PointOffset;
       public Vector2 Size;
       public LayerMask GroundLayerMask;
       Rigidbody2D Rig;
       float velocityX;
       bool GravatySwitch = true;
       bool IsOnGround;//判定是否在地面

       private void Awake()
      {
           Rig = GetComponent<Rigidbody2D>();
      }
       private void FixedUpdate()
      {
           IsOnGround = OnGround();
           //左右移动
           if (Input.GetAxisRaw("Horizontal") < 0)
          {
               Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60*(-1), ref velocityX, AccelerrateTime), Rig.velocity.y);
          }
           else if (Input.GetAxisRaw("Horizontal") > 0)
          {
               Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60, ref velocityX, AccelerrateTime), Rig.velocity.y);
          }
           else if (Input.GetAxisRaw("Horizontal") == 0)
          {
               Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, 0, ref velocityX, AccelerrateTime), Rig.velocity.y);
          }
           if (Input.GetAxisRaw("Jump") == 1&&!IsJumping)
          {
               Rig.velocity = new Vector2(Rig.velocity.x, JumpingSpeed);//x轴不变,y轴给个初速度
               IsJumping = true;//正在空中
          }
           if (IsOnGround && Input.GetAxisRaw("Jump") == 0)//在地面并且松开跳跃键
          {
               IsJumping = false;
          }
           //Physics2D.gravity.y是一个负值
           if (Rig.velocity.y < 0)//下坠时
          {
               //下落的更快
               Rig.velocity += Vector2.up * Physics2D.gravity.y * (FallMultiplier - 1) * Time.fixedDeltaTime;
          }
           else if(Rig.velocity.y>0&&Input.GetAxisRaw("Jump")!=1)//当玩家上升时,并且没有按跳跃键,实现按多久跳多高,范围内任意高度跳跃
          {
               //减缓上升
               Rig.velocity += Vector2.up * Physics2D.gravity.y * (LowJumpMultiplier - 1) * Time.fixedDeltaTime;
          }
      }
       bool OnGround()
      {
           Collider2D Coll = Physics2D.OverlapBox((Vector2)transform.position + PointOffset, Size, 0, GroundLayerMask);
           //触地判定框
           if (Coll != null)
          {
               return true;
          }
           else
          {
               return false;
          }
      }
       private void OnDrawGizmos()//在编辑器中显示判定框
      {
           Gizmos.DrawWireCube((Vector2)transform.position + PointOffset, Size);
      }
    }

    冲刺+

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using DG.Tweening;
    public class Character : MonoBehaviour
    {
       //移动
       public float WalkSpeed;
       public float AccelerrateTime;
       public float DecelerateTime;
       bool CanMove=true;//冲刺时关闭移动

       //跳跃
       public float JumpingSpeed;
       public float FallMultiplier;
       public float LowJumpMultiplier;
       bool IsJumping;
       bool CanJump=true;//冲刺时关闭跳跃

       //冲刺
       bool wasDashed;//冲刺状态
       Vector2 dir;
       public float Dashedforce;
       public float DragMaxForce;
       public float DragDuration;
       public float DashWaitTime;

       //触地判定
       public Vector2 PointOffset;
       public Vector2 Size;
       public LayerMask GroundLayerMask;
       Rigidbody2D Rig;
       float velocityX;
       bool IsOnGround;//判定是否在地面
       bool GravityModifier=true;//冲刺时关闭加速度

       private void Awake()
      {
           Rig = GetComponent<Rigidbody2D>();
      }
       private void FixedUpdate()
      {
           IsOnGround = OnGround();
           #region 左右移动
           if (CanMove)
          {
               if (Input.GetAxisRaw("Horizontal") < 0)
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60 * (-1), ref velocityX, AccelerrateTime), Rig.velocity.y);
              }
               else if (Input.GetAxisRaw("Horizontal") > 0)
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60, ref velocityX, AccelerrateTime), Rig.velocity.y);
              }
               else
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, 0, ref velocityX, AccelerrateTime), Rig.velocity.y);
              }
          }
           #endregion
           #region 起跳
           if (CanJump)
          {
               if (Input.GetAxisRaw("Jump") == 1 && !IsJumping)//跳跃:给y轴一个初速度
              {
                   Rig.velocity = new Vector2(Rig.velocity.x, JumpingSpeed);//x轴不变,y轴给个初速度
                   IsJumping = true;//正在空中
              }
               if (IsOnGround && Input.GetAxisRaw("Jump") == 0)//在地面并且松开跳跃键
              {
                   IsJumping = false;
              }
          }
           #endregion
           #region 跳跃优化
           if (GravityModifier)
          {
               //Physics2D.gravity.y是一个负值
               if (Rig.velocity.y < 0)//下坠时
              {
                   //下落的更快
                   Rig.velocity += Vector2.up * Physics2D.gravity.y * (FallMultiplier - 1) * Time.fixedDeltaTime;
              }
               else if (Rig.velocity.y > 0 && Input.GetAxisRaw("Jump") != 1)//当玩家上升时,并且没有按跳跃键,实现按多久跳多高,范围内任意高度跳跃
              {
                   //减缓上升
                   Rig.velocity += Vector2.up * Physics2D.gravity.y * (LowJumpMultiplier - 1) * Time.fixedDeltaTime;
              }
          }
           #endregion
           #region 冲刺检测
           //1.不受重力影响
           //2.不受其他按键影响
           if (Input.GetAxisRaw("Dash") == 1 && !wasDashed)//冲刺之后
          {
               wasDashed = true;
               dir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));//获得冲刺方向
               //玩家所有动量清零
               Rig.velocity = Vector2.zero;
               //给玩家施加一个力,进行冲刺
               Rig.velocity += dir * Dashedforce;
               StartCoroutine(Dash());
          }
           if (Input.GetAxisRaw("Dash") == 0 && IsOnGround)
          {
               wasDashed = false;
          }
         
           #endregion
      }
       IEnumerator Dash()//冲刺
      {
           //锁定玩家的按键功能
           //关闭重力调整器
           CanMove = false;
           CanJump = false;
           GravityModifier = false;
           //关闭重力影响
           Rig.gravityScale = 0;
           //施加空气阻力,快速停下Rigidody.Drag
           DOVirtual.Float(DragMaxForce, 0, DragDuration, RigidbodyDrag);
           //等待冲刺完毕
           yield return new WaitForSeconds(DashWaitTime);
           //开启所有关闭功能
           CanMove = true;
           CanJump = true;
           GravityModifier = true;
           Rig.gravityScale = 1;//应该为4,但GravityModifier会帮我们自动修改
      }
       public void RigidbodyDrag(float x)
      {
           Rig.drag = x;
      }
       bool OnGround()//判断是否接触地面
      {
           Collider2D Coll = Physics2D.OverlapBox((Vector2)transform.position + PointOffset, Size, 0, GroundLayerMask);
           //触地判定框
           if (Coll != null)
          {
               return true;
          }
           else
          {
               return false;
          }
      }
       private void OnDrawGizmos()//在编辑器中显示判定框
      {
           Gizmos.DrawWireCube((Vector2)transform.position + PointOffset, Size);
      }
    }

    触地判定

    1. 代码显示判定框,调整判定框大小:宽度略小于物体

    2. 设置地面:地板的layer添加一个layer,并在物体的Ground layermask选中这个layer

    3. 绘画出动作每一帧,添加进Animator中,勾选loop调为连续播放

    完整

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using DG.Tweening;
    public class Move : MonoBehaviour
    {
       Rigidbody2D Rig;//定义刚体

       //移动
       public float WalkSpeed;
       public float AccelerrateTime;
       public float DecelerateTime;
       bool CanMove=true;//冲刺时关闭移动
       Animator Anim;//定义动画
       SpriteRenderer SR;

       //跳跃
       public float JumpingSpeed;
       public float FallMultiplier;
       public float LowJumpMultiplier;
       bool IsJumping;
       bool CanJump=true;//冲刺时关闭跳跃

       //冲刺
       bool wasDashed;//冲刺状态
       Vector2 dir;
       public float Dashedforce;
       public float DragMaxForce;
       public float DragDuration;
       public float DashWaitTime;

       //触地判定
       public Vector2 PointOffset;
       public Vector2 Size;
       public LayerMask GroundLayerMask;
       float velocityX;
       bool IsOnGround;//判定是否在地面
       bool GravityModifier=true;//冲刺时关闭加速度

       private void Awake()
      {
           Rig = GetComponent<Rigidbody2D>();//获得添加了此脚本的刚体
           Anim = GetComponent<Animator>();//获得添加了此脚本的动作
           SR = GetComponent<SpriteRenderer>();
      }
       private void FixedUpdate()
      {
           IsOnGround = OnGround();
           #region 左右移动
           if (CanMove)
          {
               if (Input.GetAxisRaw("Horizontal") < 0)//向左走
              {
                   if (Rig.velocity.x < WalkSpeed * Time.fixedDeltaTime * 60)
                  {
                       Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60 * (-1), ref velocityX, AccelerrateTime), Rig.velocity.y);
                  }
                   SR.flipX = true;
                   Anim.SetFloat("Walk", 0.5f);
              }
               else if (Input.GetAxisRaw("Horizontal") > 0)//向右走
              {
                   if (Rig.velocity.x < WalkSpeed * Time.fixedDeltaTime * 60)
                  {
                       Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, WalkSpeed * Time.deltaTime * 60, ref velocityX, AccelerrateTime), Rig.velocity.y);
                  }
                   SR.flipX = false;//不变
                   if (!wasDashed)
                  {
                       Anim.SetFloat("Walk", 0.5f);
                  }
              }
               else
              {
                   Rig.velocity = new Vector2(Mathf.SmoothDamp(Rig.velocity.x, 0, ref velocityX, AccelerrateTime), Rig.velocity.y);
                   if (!wasDashed)
                  {
                       Anim.SetFloat("Walk", 0f);
                  }
              }
          }
           #endregion
           #region 起跳
           if (CanJump)
          {
               if (Input.GetAxisRaw("Jump") == 1 && !IsJumping)//跳跃:给y轴一个初速度
              {
                   Rig.velocity = new Vector2(Rig.velocity.x, JumpingSpeed);//x轴不变,y轴给个初速度
                   IsJumping = true;//正在空中
              }
               if (IsOnGround && Input.GetAxisRaw("Jump") == 0)//在地面并且松开跳跃键
              {
                   IsJumping = false;
              }
          }
           #endregion
           #region 跳跃优化
           if (GravityModifier)
          {
               //Physics2D.gravity.y是一个负值
               if (Rig.velocity.y < 0)//下坠时
              {
                   //下落的更快
                   Rig.velocity += Vector2.up * Physics2D.gravity.y * (FallMultiplier - 1) * Time.fixedDeltaTime;
              }
               else if (Rig.velocity.y > 0 && Input.GetAxisRaw("Jump") != 1)//当玩家上升时,并且没有按跳跃键,实现按多久跳多高,范围内任意高度跳跃
              {
                   //减缓上升
                   Rig.velocity += Vector2.up * Physics2D.gravity.y * (LowJumpMultiplier - 1) * Time.fixedDeltaTime;
              }
          }
           #endregion
           #region 冲刺检测
           //1.不受重力影响
           //2.不受其他按键影响
           if (Input.GetAxisRaw("Dash") == 1 && !wasDashed)//冲刺之后
          {
               wasDashed = true;
               dir = GetDir();//获得冲刺方向
               //玩家所有动量清零
               Rig.velocity = Vector2.zero;
               //给玩家施加一个力,进行冲刺
               Anim.SetFloat("Dash", 1.0f);
               Rig.velocity += dir * Dashedforce;
               StartCoroutine(Dash());
          }
           if (Input.GetAxisRaw("Dash") == 0 && IsOnGround)
          {
               wasDashed = false;
               Anim.SetFloat("Dash", 0f);
          }
         
           #endregion
      }
       IEnumerator Dash()//冲刺
      {
           //锁定玩家的按键功能
           //关闭重力调整器
           CanMove = false;
           CanJump = false;
           GravityModifier = false;
           //关闭重力影响
           Rig.gravityScale = 0;
           //施加空气阻力,快速停下Rigidody.Drag
           DOVirtual.Float(DragMaxForce, 0, DragDuration, RigidbodyDrag);
           //等待冲刺完毕
           yield return new WaitForSeconds(DashWaitTime);
           //开启所有关闭功能
           CanMove = true;
           CanJump = true;
           GravityModifier = true;
           Rig.gravityScale = 1;//应该为4,但GravityModifier会帮我们自动修改
      }
       public void RigidbodyDrag(float x)
      {
           Rig.drag = x;
      }
       bool OnGround()//判断是否接触地面
      {
           Collider2D Coll = Physics2D.OverlapBox((Vector2)transform.position + PointOffset, Size, 0, GroundLayerMask);
           //触地判定框
           if (Coll != null)
          {
               return true;
          }
           else
          {
               return false;
          }
      }
       private void OnDrawGizmos()//在编辑器中显示判定框
      {
           Gizmos.DrawWireCube((Vector2)transform.position + PointOffset, Size);
      }
       public Vector2 GetDir()
      {
           Vector2 tempDir= dir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
           if (tempDir.x == 0 && tempDir.y == 0)
          {
               if (!SR.flipX)
                   tempDir.x = 1;
               else
                   tempDir.x = -1;
          }
           return tempDir;
      }
    }

    问题:只能实现一段跳

    制作完美手感二段跳

     private void Update()//避免多次按跳跃键落地后自动跳,
      {
           JumpPressed = false;
           if (Input.GetButtonDown("Jump")&& JumpCount>0)
          {
               JumpPressed = true;
          }
           #region 起跳
           if (CanJump)
          {
               if (JumpPressed && JumpCount > 0 && !IsOnWall)
              {
                   Rig.velocity = new Vector2(Rig.velocity.x, JumpingSpeed);//x轴不变,y轴给个初速度
                   JumpCount--;
                   JumpPressed = false;
                   //正在空中
              }
               else if (IsOnGround)//在地面并且松开跳跃键
              {
                   JumpCount = JumpCountNumber;
                   IsJumping = false;
              }
          }
           #endregion
      }
       private void FixedUpdate()
      {
           if (CanJump)
          {
               if (JumpPressed &&!IsOnWall)
              {
                   Rig.velocity = new Vector2(Rig.velocity.x, JumpingSpeed);//x轴不变,y轴给个初速度
                   JumpCount--;
                   JumpPressed = false;
                   //正在空中
              }
               else if (IsOnGround)//在地面并且松开跳跃键
              {
                   JumpCount = JumpCountNumber;
              }
          }
      }
    1. 如果跳跃代码全在update中,跳跃可能无法二段

    2. 如果全在fixedupdate中,点击一次两端jumpcount一起消失

  • 相关阅读:
    django框架个人博客实战
    django框架简介
    Nginx 反向代理设置
    Nginx 动静分离设置
    nginx 安装
    nginx-简介及概念
    自己的Qt GUI 项目+vs2013+opencv+caffe环境配置
    机器学习实战之K-Means算法
    机器学习实战之树回归
    机器学习实战之回归
  • 原文地址:https://www.cnblogs.com/yylblog/p/13954204.html
Copyright © 2011-2022 走看看