Phaser 3最新版 Graphics生成纹理后Sprite尺寸异常如何正确设置
问题根因
核心问题出在graphics.generateTexture('hex')的调用逻辑:
- 该方法如果不手动传入纹理宽度、高度参数,Phaser 3会默认使用当前游戏的全画布尺寸(即你配置的1920*1080)作为生成纹理的大小。你绘制的六边形仅占这张全屏大纹理的极小部分,其余区域全是透明像素,因此创建Sprite后读取到的displayWidth、displayHeight就是全屏尺寸。
- 额外偏差来自绘制坐标:你传入Graphics的六边形顶点是叠加了世界坐标偏移的数值,没有做局部坐标转换,六边形在大纹理中的位置本身就是偏移的,缩放时就会出现只显示一角、图形几乎不可见的问题。
修复方案
1. 修正纹理生成逻辑
生成纹理前先计算六边形的实际边界,将顶点转换为相对于纹理原点的局部坐标,同时给generateTexture传入准确的宽高参数,预留描边宽度避免内容被裁切:
function GraphicsCreator(scene, hexShape, hex) { // 计算六边形几何边界,预留和线宽一致的内边距防止描边裁切 const bounds = hexShape.getBounds() const padding = 3 const texWidth = Math.ceil(bounds.width) + padding * 2 const texHeight = Math.ceil(bounds.height) + padding * 2 const graphics = scene.add.graphics({ x: 0, y: 0, add: false }); graphics.lineStyle(3, hex.outlineColour) graphics.fillStyle(hex.colour); // 所有顶点转换为纹理局部坐标:减去边界偏移,加上内边距 graphics.beginPath(); const firstPoint = hexShape.points[0] graphics.moveTo(firstPoint.x - bounds.x + padding, firstPoint.y - bounds.y + padding); for (let i = 1; i < hexShape.points.length; i++) { const p = hexShape.points[i] graphics.lineTo(p.x - bounds.x + padding, p.y - bounds.y + padding); } graphics.closePath(); graphics.strokePath(); graphics.fillPath(); // 传入准确宽高生成纹理,禁止使用默认全屏尺寸 graphics.generateTexture('hex', texWidth, texHeight) graphics.destroy(); // 存储纹理对应的定位偏移量,供后续创建Sprite使用 hex.texWidth = texWidth hex.texHeight = texHeight hex.spritePosX = bounds.x - padding hex.spritePosY = bounds.y - padding }
2. 修正Sprite创建逻辑
不要硬写Sprite的display宽高或缩放值,直接使用纹理自带的尺寸,坐标对齐纹理对应的世界位置:
function TextureGetter(scene, hex) { // 原点设为左上角,坐标对齐纹理实际对应的世界位置 const sprite = scene.add.sprite(hex.spritePosX, hex.spritePosY, 'hex') sprite.setDisplayOrigin(0) return sprite }
Phaser 3 Sprite尺寸设置注意事项
displayWidth、displayHeight是引擎自动计算的属性,不建议手动赋值,它的取值 = 纹理原始尺寸 * Sprite缩放值,手动硬写会打乱渲染比例。- 需要调整Sprite大小时,统一使用
sprite.setScale(scaleValue)方法,引擎会自动更新display宽高和碰撞边界。 - 用Graphics生成纹理时必须显式传入宽高,永远不要依赖默认的全屏尺寸参数。
- 你项目中的scale适配配置(FIT模式+居中)和本次问题无关,不需要修改。
- 现有逻辑中仅在id为1的六边形上生成一次纹理是合理的,相同样式的六边形复用同一张纹理即可,不需要重复生成浪费性能。
内容的提问来源于stack exchange,提问作者JonHerbert
相关产品推荐
相关产品推荐

