基于HybridCLR做的一个FlyBird Demo

news2024/12/27 9:59:58

周末学习了下HybridCLR的原理和用法做了个FlyBrid小demo。记录一下

官网里写的原理:

对于这个我的理解是:

Unity引擎的代码使用还是AOT方式。对于项目业务这块打成多个程序集。运行时使用了解释器,解释执行。从而完成热更新。

一。环境安装

工作安装HyBridClr包如图

工程改成IL2CPP模式(如果报错,安装Unity对应平台的IL2CPP包)

点击多出来的菜单中的HyBrid的Install按钮进行环境安装。

二。Demo制作

看作者所说,这个工具如果是Prefab上挂脚本的方式,需要打成AssetBundle方式或者是项目运行时动态加载才能起到效果。这里我就使用第一种方式。

项目写的比较简单就贴一点关键代码吧:

游戏管理类:

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

public enum GameState
{
    Start = 0,
    Begin = 1,
    Playing = 2,
    End = 3,
}
public class EntryManager :MonoBehaviour
{
    public GameObject m_StartBtn;
    public GameObject m_TryBtn;
    public GameObject m_SceneBg1;
    public SceneManager m_SceneBg2;
    public Bird m_BirdGo;
    public Text m_ScoreText;
    public GameState m_State = GameState.Start;
    
    private int m_Score = 0;
    private static EntryManager m_Instance;
    public static EntryManager Instance
    {
        get
        {
            return m_Instance;
        }
    }
    public void Start()
    {
        m_Instance = this;
        ToolHelper.SetClicked(m_StartBtn,OnStartClicked);
        ToolHelper.SetClicked(m_TryBtn,OnStartClicked);
    }
    public void GameInit()
    {
       
    }

    public void AddScore()
    {
        m_Score = m_Score + 5;
        m_ScoreText.text = m_Score.ToString();
    }
    public void OnStartClicked()
    {
        m_Score = 0;
        m_ScoreText.text = "0";
        m_ScoreText.gameObject.SetActive(true);
        BeginStart();
    }

    public void BeginStart()
    {
        m_BirdGo.BeginGame();
        m_StartBtn.gameObject.SetActive(false);
        m_TryBtn.gameObject.SetActive(false);
        m_SceneBg2.gameObject.SetActive(true);
        m_SceneBg2.BeginPlay();
        m_SceneBg1.SetActive(false);
        m_State = GameState.Playing;
    }

    public void GameOver()
    {
        Debug.Log("GameOver");
        m_State = GameState.End;
        //m_ScoreText.gameObject.SetActive(false);
        m_TryBtn.gameObject.SetActive(true);
        m_SceneBg2.gameObject.SetActive(false);
        m_SceneBg1.SetActive(true);
        
    }
    
    
}

飞鸟类:

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

public class Bird : MonoBehaviour
{
    public Rigidbody2D m_RigidBody;
    public Image m_Sprite;
    public int m_Index = 0;
    public List<Sprite> m_Sprite1;
    public List<Sprite> m_Sprite2;
    private List<Sprite> m_CurrentSprite;
    public int m_Frame = 0;
    public float m_CurSpeed;
    public float m_DownAdSpeed;
    public float m_UpAdSpeed;
    public void Awake()
    {
        m_CurrentSprite = m_Sprite1;
    }

    public void BeginGame()
    {
        transform.localPosition = Vector3.zero;
        m_CurSpeed = 0;
    }

    public void FixedUpdate()
    {
        ++m_Frame;
        if (m_Frame >= 5)
        {
            m_Frame = 0;
            m_Index = ++m_Index % m_CurrentSprite.Count;
            m_Sprite.sprite = m_CurrentSprite[m_Index];
        }

        if (transform.localPosition.y >= 520 || transform.localPosition.y <= -400)
        {
            EntryManager.Instance.GameOver();
        }
        if (EntryManager.Instance == null)
            return;
        if (EntryManager.Instance.m_State == GameState.Playing)
        {
            m_CurSpeed -= m_DownAdSpeed;
            if (m_CurSpeed < -6.5f)
            {
                m_CurSpeed = -6.5f;
            }
            transform.localPosition += Vector3.up * m_CurSpeed;
        }
    }

    public void Update()
    {
        if (EntryManager.Instance == null)
            return;
        if (EntryManager.Instance.m_State == GameState.Playing)
        {
            if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0))
            {
                m_CurSpeed = m_UpAdSpeed;
            }
        }
    }

    public void SetBirdImg(int index)
    {
        if (index == 0)
        {
            m_CurrentSprite = m_Sprite1;
        }
        else
        {
            m_CurrentSprite = m_Sprite2;
        }
    }
}

场景管理类:

using System.Collections;
using System.Collections.Generic;
//using System.Numerics;
using UnityEngine;

public class SceneManager : MonoBehaviour
{
    public SingleScene m_Bg1;
    public SingleScene m_Bg2;
    public SingleScene m_Bg3;
    public float m_ScollSpeed = 10;
    //private bool m_IsFirstPass = false;
    public float m_LeftBorad = -750;
    public void BeginPlay()
    {
        //m_IsFirstPass = false;
        m_Bg1.transform.localPosition = Vector3.zero;
        m_Bg2.transform.localPosition = new Vector3(750,0,0);
        m_Bg3.transform.localPosition = new Vector3(1500,0,0);
        gameObject.SetActive(true);
        m_Bg1.ChangeScene();
        m_Bg1.ShowGuanzi(false);
        m_Bg2.ChangeScene();
        m_Bg3.ChangeScene();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (EntryManager.Instance == null)
            return;
        if (EntryManager.Instance.m_State == GameState.Playing)
        {
            float moveDis = m_ScollSpeed;
            MoveSingleScene(m_Bg1, moveDis);
            MoveSingleScene(m_Bg2, moveDis);
            MoveSingleScene(m_Bg3, moveDis);
        }
    }

    private void MoveSingleScene(SingleScene scene,float dis)
    {
        scene.m_Tf.anchoredPosition += dis * Vector2.left;
        if (scene.m_Tf.anchoredPosition.x <= m_LeftBorad)
        {
            //Debug.Log("Move:" + time);
            scene.m_Tf.anchoredPosition = new Vector2(1500, 0);
            scene.ChangeScene();
            if(scene == m_Bg1)
                m_Bg1.ShowGuanzi(true);
        }
    }
}

这些类一定是要放在一个程序集里进行执行,因为后来是要对程序集进行打包

三。打包Dll

点击菜单:

在对应目录下会生成Dll文件

加个后缀.bytes

放进工程的StreamAsset文件夹下,并且把之前做的入口管理Prefab打成AssetBundle也放进去。

修改官方demo中的loaddll代码。

如图:

最后build测试:

比较顺利,没什么问题。

总结下来:

在整个Demo开发的时候确实没有什么非要注意的潜规则,确实如作者所说几乎0成本接入。后续等如果有机会运用到项目中再说。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2099138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL5.6迁移到DM8

注意&#xff1a; MySQL 5.7 与 MySQL 8.0 的语法有所区别&#xff0c;本文档是将MySQL5.6迁移到DM8。 迁移前准备 源库 数据库信息 统计源端业务库要迁移的数据量、字符编码、归档保留等信息。 内容 说明 备注 数据库架构 单机 节点数 1 数据库版本 MySQL 5.6…

OpenGL/GLUT实践:实现反弹运动的三角形动画与键盘控制(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub&#xff1a;A-UESTCer-s-Code 文章目录 1 运行效果2 实验过程2.1 环境配置2.2 绘制三角形2.2.1 渲染函数2.2.2 主函数2.2.3 运行结果 2.3 调整窗口大小2.4 简单动画与按键控制2.4.1 简单旋转2.4.2 键盘控制 2.5 窗口反弹动画2.5.1 处理窗口大小变化2.5.2 渲染函数…

【Redis】缓存(下)

经过缓存这篇文章的概述&#xff0c;已经对缓存有了初步的了解和认知。在本篇文章中&#xff0c;主要是通过代码来实现缓存的应用&#xff0c;以及在使用缓存过程中出现的经典问题。 简单应用 需求&#xff1a;根据菜品id来查询缓存 流程&#xff1a;① 从缓存中查询&#x…

『功能项目』怪物的信息显示【15】

本章项目成果展示 我们打开上一篇14怪物反击主角复活的项目&#xff0c; 本章要做的事情是当主角进入怪物的攻击范围之内时显示怪物的血量信息 在Canvas创建一个空物体 将空物体GameObject钉到视角上方 重命名为KingInfoUI 在子级创建一个Image 在资源文件夹下创建一个空文件命…

【数据结构 | 每日一题】图的概念辨析

图的概念辨析 考点分析&#xff1a;我们学习数据结构图的第一小节就是&#xff1a;图的基本概念&#xff0c;我们会发现图的概念非常多且有些概念之间又很像&#xff0c;而对于初学者来说&#xff0c;相比树的概念是不好理解的&#xff0c;很容易搞混&#xff0c;因此做了这么…

Tapd敏捷开发平台的使用心得

Tapd敏捷开发平台的使用心得 一、Tapd 简介 TAPD(Tencent Agile Product Development),腾讯敏捷产品研发平台行业领先的敏捷协作方案,贯穿敏捷产品研发生命周期的一站式服务,了解敏捷如下图 二、几个核心模块概念 需求迭代缺陷故事墙前期项目需求的管理,可以按类别建…

如何交叉编译 Linux v4l-utils 依赖库?

本文将以在 Ubuntu 20.04 系统的 x86_64 机器上&#xff0c;为 aarch64 架构的嵌入式机器&#xff0c;交叉编译 v4l-utils&#xff08;libv4l&#xff09;为例&#xff0c;进行介绍。 安装编译 v4l-utils 所需的依赖库。 $ apt update $ apt install make automake libtool安…

【docker】docker 简介

docker 简介 是什么虚拟化、容器化案例为什么要虚拟化、容器化&#xff1f; 是什么虚拟化、容器化 物理机&#xff1a;实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境&#xff0c;有时也称为“寄主”或“宿主”。 虚拟化&…

【时间盒子】-【3.新建项目】创建元服务工程,选择默认模板Empty Ability

一、新建项目 1、打开DevEco Studio >>文件>>新建>>新建项目&#xff0c;选择元服务 Atomic Service>>默认模板Empty Ability。 2、设置元服务的工程名称、Bundle name等&#xff0c;模型选Stage&#xff0c;语言是ArkTS&#xff0c;支持的设备类型只…

异步并发处理利器:在 Jupyter Notebook 中玩转 asyncio

asyncio.run报错 RuntimeError: asyncio.run() cannot be called from a running event loop 在jupyter notebook中运行下述代码就会出现上述报错 import uvicorn from fastapi import FastAPI from fastapi.responses import JSONResponse app FastAPI() app.get(“/”) d…

Openwrt 安装 AX210 无线网卡

安装 TTYD 我安装的是官方原版的 Openwrt&#xff0c;首先需要安装 YYTD 来从网页控制 Openwrt。 安装驱动 参考这个链接&#xff0c;跟着做。 iwlwifi-firmware-ax210 我买设备技术提供代码如下&#xff0c;但是没有安装 成功&#xff0c;中间报错。 opkg update opkg i…

<el-table> 把表格内同一列相同的数据合并为一行

<el-table> 把表格内同一列相同的数据合并为一行 具体效果如下图&#xff1a; 参考代码&#xff08;可直接运行&#xff09;&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"/><meta name"viewport" co…

SpringBoot中基于MongoDB的findAndModify原子操作实现分布式锁原理详解

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

html简单注册页面

简单的html注册页面&#xff0c;代码如下&#xff0c;效果如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…

Linux | 匿名管道和命名管道:进程间通信数据流的桥梁

目录 1、进程间通信目的 2、管道——匿名管道和命名管道 匿名管道 匿名管道的示例代码&#xff1a;将数据写入管道、子进程从管道读取数据并将其输出到bash中 父子进程通过匿名管道建立通信 重点&#xff1a;管道的五个特点 命名管道&#xff08;也称为FIFO&#xff09;…

Java项目:128 基于Spring Boot的装饰工程管理系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统包含管理员、员工和客户角色 管理员权限操作的功能包括管理合同信息&#xff0c;管理合同报价&#xff0c;管理立项项目&#xff0c;管…

机器学习:opencv--图像边缘检测

目录 前言 一、图像边缘检测 1.边缘检测 2.边缘检测的方法 二、Sobel算子 1.Sobel算子 2.计算 3.代码实现 4.代码步骤解析 1.导入图片 2.处理x轴和y轴的边缘并相加 三、Scharr算子 1.Scharr算子 2.计算 3.代码实现 四、Laplacian算子 1.Lapla…

本地部署训练、测试controlnet的完整过程(包括报错和代码)

文章目录 参考内容一、训练流程下载相关文件① 需要下载的权重文件② 下载数据集 二、训练代码两种训练方式&#xff1a;①采用.sh文件②常规的训练 测试代码生成的结果 四、报错NVIDIA的驱动太老需要更新生成出全黑图 参考内容 diffusers库提供的官方训练代码 利用到的fill50…

Vue(六) render函数、Vue.config.js配置文件,ref属性,props配置项、mixin混入、插件、scoped

文章目录 一、render函数二、Vue.config.js配置文件三. ref属性四. props配置项五. mixin混入1. 局部混入2. 全局混入 六. 插件七. scoped 一、render函数 在main.js文件中&#xff0c;采用了render函数。 import App from ./App.vuenew Vue({// 这句代码的意思是将App组件放…

Springboot整合J2cache实现声明式缓存方案

Springboot整合J2Cache 一、J2Caceh多级缓存 ​ J2Cache 是 OSChina 目前正在使用的两级缓存框架&#xff08;要求至少 Java 8&#xff09;。 ​ 第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine)&#xff0c;第二级缓存使用 Redis(推荐)/Memcached 。 L…