【GamePlay】入门篇

游戏性编程是指通过一系列游戏系统将游戏想法变成现实的过程。

本次的简例以NPC设计为主。

通常在进行脚本设计前,对NPC的属性进行基本的添加和设定,诸如动画系统、物理系统等等。

1.动画系统

添加Animator组件,绑定骨骼。

创建Animator Controller文件,将之添加到组件的Controller部分。

打开Controller,考虑动画组件的主体需要实现什么功能。

以此例的NPC为例,需要实现他的移动功能。

所以在Controller中添加新的混合树命名为Locomotion(移动)。

打开混合树,为其添加三种不同的运动状态(空闲、走路、奔跑),并绑定相应的动画文件。

调整三个状态之间的数值阶段,初始为0:0.5:1,调整为0:1:8。

(这里的意义在于更流畅的移动体验,休闲到走路快速的过渡,走路到奔跑则需要速度到达一定阈值后才能切换。)

备注:

取消勾选Autonate Thresholds后,可以更改数值。

parameter是用于脚本中调用setFloat方法中的参数名,从而在动画间不断的切换。

【2】Player脚本

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

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed;
    private Vector3 moveInput;
    private Vector3 moveVelocity;

    private Rigidbody rd;

    private Camera mainCamera;
    private Animator animator;

    // Start is called before the first frame update
    void Start()
    {
        rd = GetComponent<Rigidbody>();
        mainCamera = Camera.main;
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        
        float lh = Input.GetAxis("Horizontal");//输入的是左右,即X轴数据,对应着AD键位。
        float lv = Input.GetAxis("Vertical");//输入的是上下,即Z轴的数据,对应着WS键位。
       
        moveInput =new Vector3(lh,0f,lv);
        //一个即时的向量,当无输入时是零向量。
        //在Unity中,人物面朝的方向是蓝轴,即Z轴;沿着人物双手方向的横轴是红轴,即X轴;||而沿着人物垂心的是绿轴,即Y轴。
        Vector3 cameraForword = mainCamera.transform.forward;
        //主相机在沿着z轴的矢量位置和方向
        
        cameraForword.y = 0;
        Quaternion s = Quaternion.FromToRotation(Vector3.forward, cameraForword);
        //这个四元素包含了(0,0,1)到cameraForword的旋转信息
        
        Vector3 lookToward = s * moveInput;
        //四元数和向量相乘表示这个向量按照这个四元数进行旋转之后得到的新的向量。

        if (moveInput.sqrMagnitude>0)
        {
            Ray ray = new Ray(transform.position,lookToward);
            //transform.position为该脚本对应的对象的位置
           
            transform.LookAt(ray.GetPoint(1));
            //transform.LookAt:旋转自身,使得当前对象的正z轴指向目标对象target所在的位置(使对象朝向目标点)
            //ray.GetPoint(1):获取一个沿着向量方向距离X的点
        }
        moveVelocity = transform.forward*moveSpeed* moveInput.sqrMagnitude;
        //transform.forward给的是人物坐标轴Z轴的矢量方向,即面朝的方向
        //(自动对物体旋转值算出前进方向向量的变量,vector3.forward则不计算旋转值,所以vector3.forward固定为(0,0,1))
        //moveVector3.sqrMagnitude返回是坐标轴输入矢量的平方长度的Float数值,用于控制速度,当无输入时,速度为0。
        Aniamting();
    }

    void FixedUpdate()
    {
        rd.velocity = moveVelocity;
    }

    void Aniamting()
    {
        animator.SetFloat("Blend",rd.velocity.magnitude);
        //调用animator.SetFloat方法,可以设置混合树中的参数数值,参数名字以自定义的参数名为准
    }
}

 【3】scriptableobject(Unity中用于处理序列化的结构)

一个允许你存储大量独立于脚本实例的共享数据的类。

目的是通过避免对值进行复制而减少内存的开销。

定义了一个继承自ScriptableObject的类,你可以使用CreateAssetMenu attribute用你的类创建自定义assets。

下面为实例:

Player加载的类

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

public class CharacterStats : MonoBehaviour
{
    //Stats:一个统计玩家数据的类
    #region MyRegion
    //#region 是 C# 预处理器指令。 #region 是一个分块预处理命令,它主要是用于编辑器代码的分块,在编译时会被自动删除。
    //#region 在使用 Visual Studio 代码编辑器的大纲显示功能时指定可展开或折叠的代码块。有助于代码的整洁。
    //
    public static CharacterStats instance;

    void Awake()
    {
        instance = this;//传递自身的地址
    }

    #endregion
    public int MaxHealth = 100;
    public int CurrentHealth { get; private set; }
    //可以公共获取,但只能在该类中设置。

    void Start()
    {
        CurrentHealth = MaxHealth;
    }

    public void takeDamage(int damage)
    {
        CurrentHealth -= damage;
        if (CurrentHealth <= 0)
        {
            Dead();
        }
    }

    public void TreatHealth(int treat)
    {
        print("treat:"+treat);
        CurrentHealth += treat;
        print(CurrentHealth);
        if (CurrentHealth >= 100)
        {
            print("你恢复了健康");
        }
    }

    public void Dead()
    {
        print("You Dead");
    }

}

互动对象体加载的类:

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

public class ItemPickUp : Interacrable
{
    //继承自Interacrable类(含有与环境互动的代码)
    public Itemss item;
   CharacterStats charStatss=new CharacterStats();

    public override void Interact()//重写了父类的方法,并搭载的自己的内容
    {base.Interact();
        PickUp();
    }

    void PickUp()
    {
        item.Use();//这里使用的派生类的基类,但实际上传递的是根据Item基类自定义的assets。
        Destroy(gameObject);
    }
}

以下是相关的类,并未直接加载到对象上:

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

[CreateAssetMenu(fileName = " NewItems",menuName = "Inventory/Item")]

public class Itemss : ScriptableObject
{//创建assets的基类
    new public string name = "Item";
    public Sprite icon = null;

    public virtual void Use()
    {
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Health Potion",menuName = "Inventory/Item/Health Potion")]
public class HealthPotion : Itemss
{
    //继承自Item类的子类,是assets新的蓝本。
    public int HealthModifity;
    private CharacterStats charStats;

    void Start()
    {
        charStats=CharacterStats.instance;
    }

    public override void Use()
    {
        base.Use();
        ApplyEffect();
    }

    void ApplyEffect()
    {
        CharacterStats.instance.TreatHealth(HealthModifity);//传递了玩家参数类的方法。
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Interacrable : MonoBehaviour
{
    //包含玩家与环境互动的类
    public bool interacting = false;
    private Renderer rend;

    public Material[] materials;
    void Start()
    {
        rend = GetComponent<Renderer>();
        rend.enabled=true;//启用渲染器,使渲染的对象可见
        rend.sharedMaterial = materials[0];
        //Renderer.sharedMaterial:修改模型材质的颜色,或者是修改材质Shader的一些属性。
        //(此方法使用的材料是共享的材料,内存中只有一份,不建议对材料做修改)
    }
    void Update()
    {
        if (interacting&&Input.GetKeyDown(KeyCode.Alpha1))
        {Interact();
        }

        if (interacting)
        {
            rend.sharedMaterial = materials[1];
        }
        else
        {
            rend.sharedMaterial = materials[0];
        }
    }

    public virtual  void Interact()
    {//虚方法,子类可加Override进行重写,虚方法本身有方法体。
        Destroy(gameObject);
    }

    void OnTriggerEnter(Collider other)
    {
       
        if (other.gameObject.tag == "Player")
        {
            interacting = true;
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            interacting = false;
        }
    }
}

 

posted on 2019-07-03 20:27  青先生 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/Mr-QingZi/p/11128829.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UE4中的Gameplay框架是一个强大的工具集,用于开发和实现游戏玩法和用户交互。该框架提供了许多功能和组件,以帮助游戏开发者快速构建出丰富、流畅的游戏体验。 UE4的Gameplay框架主要由以下几个方面组成: 1.输入系统:该系统可以处理各种输入设备的操作,如鼠标、键盘和游戏手柄。开发者可以轻松地设置和管理输入映射和按键绑定。此外,还提供了鼠标和手柄的即时响应和移动方向控制功能,使玩家能够自由操作游戏中的角色。 2.角色控制器:角色控制器是游戏玩家在游戏中扮演的角色,他们的控制是通过输入系统和蓝图来实现的。游戏玩家可以移动角色、执行动作、攻击敌人等。角色还可以通过动画系统实现自然的运动和交互。 3.人工智能:UE4的Gameplay框架提供了内置的人工智能系统,可以对NPC和敌人进行编程控制。开发者可以设置敌人的行为模式、路径寻找和攻击策略,让游戏中的敌人具有更真实和智能的表现。 4.物理模拟:UE4的Gameplay框架使用了物理引擎来实现真实的物理模拟效果,比如碰撞、重力和刚体运动等。这使开发者能够创建更真实和具有交互性的游戏世界,使玩家可以与环境进行互动。 总之,UE4的Gameplay框架提供了强大而灵活的工具,帮助开发者轻松地构建出丰富多样的游戏玩法和用户交互。无论是开发动作冒险游戏、射击游戏还是角色扮演游戏,该框架都能满足开发者的需求,并带来令人惊叹的游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值