【UnityDOTS 二】Entity的理解

Entity的理解

Entity作为一种对CPU的Cache友好的编码方式,是DOTS中重要的编码流程与思想。需要程序员由OOP的思想转为DOD的思想,即:面向数据的编码方式。

Unity的ECS:
Entity:只是一个代表,用于快速查找数据等
Component:只有数据的Struct,无法被引用(特殊手法可以),大量相同的Component并排在内存中,可以提高Cache的命中率,以及Burst编译器生成SIMD命令提高性能。
System:用于处理Component的类,包含真正的处理逻辑,有一套自己的生命周期管理。可以遍历筛选出自己需要的Component进行处理。在System中可以结合JOBS来进一步提升性能。

一、Entity是什么?

Entity在DOTS的ECS系统中,只是作为一个包装的概念,看下官方文档的解释。
在这里插入图片描述
简单理解就是一个Struct,里面包含两个数据,Index以及Version。Index指向Entity在EntityWorld中的编号,Version则是版本号。因为Index会被复用,所以销毁一个Enity,又创建一个的时候,这个Index会被复用,然后通过Version就可以判定一个唯一的Enity了。

二、Entity的创建

1.Authoring模式

Authoring模式,在subScene中创建一个GameObject,Unity会隐式使用一个叫做Bake的过程,把托管的GameObject转换成对应的Entity(以及附带的各种内部Component)。
我们还需要用自定义的Component,这个时候,可以在对应的Monobehaviour脚本中,添加一个继承Baker的类,来转换你想要的Enity,以及动态添加自定义的Component

struct RotateSpeed : IComponentData
    {
        public float rotateSpeed;
    }
    public class RotateSpeedAuthoring : MonoBehaviour
    {
        [Range(0, 360)]public float rotateSpeed = 360.0f;
        public class Baker : Baker<RotateSpeedAuthoring>
        {
            public override void Bake(RotateSpeedAuthoring authoring)
            {
                var entity = GetEntity(TransformUsageFlags.Dynamic);
                var data = new RotateSpeed
                {
                    rotateSpeed = math.radians(authoring.rotateSpeed)
                };
                AddComponent(entity,data);
            }
        }
    }

以上代码就是将一个挂载了RotateSpeedAuthoring脚本的GameObject转换成一个Entity的过程。同时还为这个Entity添加了RotateSpeed的自定义Component

注意:Baker是增量bake的。

/// <summary>
        /// Called in the baking process to bake the authoring component
        /// </summary>
        /// <remarks>
        /// This method will be called for every instance of TAuthoringType in order to bake that instance.
        /// </remarks>
        /// <param name="authoring">The authoring component to bake</param>
        public abstract void Bake(TAuthoringType authoring);

备注:BakingSystem:用于控制Bake产出的Entity行为,相当于bake转换Entity时,可以通过这个类来控制对应的Entity产出,比如:可以给某些entity转换时,都加上一个Component数据。避免一个个在各个Bake里面手动加代码。

2.Runtime模式

World:Entity的集合,每个Entity在一个World中ID唯一,但是Unity中可以有多个World,各个World中的Entity可能有相同的ID。
EntityManager:管理他自身所在World中的所有Entity,可以创建,销毁Entity,也可以增、删、刷新Entity中的Component数据

ComponentData与Entity具有一定的映射关系,同时ComponentData因为是Struct类型,所以无法(一般情况下)在托管对象进行引用从而管理里面的数据。

创建Entity流程:
1.创建World或者获取一个World;2.拿到World中的EnityManager,创建一个Entity;3.,同时也可以通过这个EntityManager来管理Entity上的Component;4.通过创建的Entity来获取EntityAcheType来实例化更多同类型Entity;5.对应的System就可以实现对这些Entity进行逻辑处理了。

备注:Entity之间没有父子之类的关系,但是可以通过Parent组件来体现这种关系。

var generator = SystemAPI.GetSingleton<CubeGeneratorByPrefab>();
            var cubes = CollectionHelper.CreateNativeArray<Entity>(generator.cubeCount, Allocator.Temp);
            state.EntityManager.Instantiate(generator.cubeEntityProtoType, cubes);
            int count = 0;
            foreach (var cube in cubes)
            {
                state.EntityManager.AddComponentData<RotateAndMoveSpeed>(cube, new RotateAndMoveSpeed
                {
                    rotateSpeed = count*math.radians(60.0f),
                    moveSpeed = count
                });
                var position = new float3((count - generator.cubeCount * 0.5f) * 1.2f, 0, 0);
                var transform = SystemAPI.GetComponentRW<LocalTransform>(cube);
                transform.ValueRW.Position = position;
                count++;
            }
    
            cubes.Dispose();

其中:SystemAPI.GetSingleton可以用来获取唯一的组件如上图的:CubeGeneratorByPrefab在这里插入图片描述

总结

ECS作为DOTS中的一种面向数据的设计思想,理解内核还是很重要的,后续再加上其他内容

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Spring MVC的ResponseEntity类来下载进制流。例如: ``` @GetMapping("/download") public ResponseEntity<byte[]> downloadFile() throws IOException { byte[] data = // 获取进制数据 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", "file.txt"); return new ResponseEntity<>(data, headers, HttpStatus.OK); } ``` 其中,byte[]为进制数据,headers设置文件类型为进制流和文件名,HttpStatus.OK表示请求成功。 ### 回答2: 在Spring框架中,可以使用ResponseEntity来下载进制流。ResponseEntity是一个通用的返回对象,它可以包含HTTP响应的状态码、头部信息和响应体。 首先,我们需要使用HttpClient或者RestTemplate发送HTTP请求获取到包含进制流的响应体。然后,创建一个ResponseEntity对象,将获取到的进制流设置为响应体,并设置Content-Type和Content-Disposition头部信息。 以下是一个使用RestTemplate下载进制流的示例代码: ```java RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); // 设置请求头部信息 headers.set(HttpHeaders.CONTENT_TYPE, "application/octet-stream"); headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=test.txt"); // 发送GET请求 ResponseEntity<byte[]> response = restTemplate.exchange("http://example.com/download", HttpMethod.GET, new HttpEntity<>(headers), byte[].class); // 获取响应体 byte[] binaryData = response.getBody(); // 将进制流保存到本地文件 try (OutputStream outputStream = new FileOutputStream("test.txt")) { outputStream.write(binaryData); outputStream.flush(); System.out.println("文件下载完成"); } catch (IOException e) { e.printStackTrace(); } ``` 以上代码中,我们使用RestTemplate发送一个GET请求,并设置请求头部信息。然后,通过exchange方法获取到响应体的进制流,并保存到本地文件中。 需要注意的是,需要根据实际情况设置Content-Type和Content-Disposition头部信息,以确保下载的文件可以正确显示和保存。 总结起来,使用ResponseEntity下载进制流的步骤包括发送HTTP请求获取响应体,创建ResponseEntity对象,将进制流设置为响应体,并设置头部信息。最后,可以将进制流保存为文件或者进行其他处理。 ### 回答3: ResponseEntity是Spring框架提供的一个用于封装HTTP响应的类,它可以包含响应的状态码、响应头和响应体等信息。可以通过ResponseEntity来下载进制流。 首先,我们需要创建一个请求地址的URL对象。然后,使用Java的URL.openConnection()方法打开一个连接,并将连接强制转换为HttpURLConnection类型,便于设置请求的参数。 设置连接的请求方法为GET,即发送一个GET请求,获取服务器返回的响应流。然后,可以通过调用连接的getInputStream()方法获取服务器返回的输入流。 接下来,可以创建一个ByteArrayOutputStream对象,用于将输入流中的数据写入到内存中的字节数组中。我们可以创建一个缓冲区变量,每次读取一部分数据,然后将数据写入到ByteArrayOutputStream中,直到数据读取完毕。 最后,将ByteArrayOutputStream中的字节数组作为响应体返回给客户端。可以使用ResponseEntity的静态方法ok()来创建一个成功的响应,设置响应的状态码为200,并将字节数组作为响应体返回。 示例代码如下: ```java import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public ResponseEntity<byte[]> downloadBinaryFile() { try { // 请求地址 String fileUrl = "http://example.com/file.bin"; URL url = new URL(fileUrl); // 打开连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); // 获取输入流 InputStream inputStream = connection.getInputStream(); // 写入字节数组 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } byte[] fileBytes = outputStream.toByteArray(); // 设置响应头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", "file.bin"); // 返回响应实体 return ResponseEntity.ok().headers(headers).body(fileBytes); } catch (Exception e) { e.printStackTrace(); // 返回错误响应 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } ``` 上述代码可以将指定URL的进制文件下载,并将文件的字节数组作为响应体返回给客户端。同时,还设置了响应头用于指定文件名称和文件类型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值